@bendyline/gezel-service 1.0.7 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/dist/bin/gezeld.js +6253 -3616
  2. package/dist/handboek-content/whats-new/1.26224.md +1 -0
  3. package/dist/handboek-content/whats-new/1.26226.md +1 -0
  4. package/dist/handboek-content/whats-new/1.26231.md +1 -0
  5. package/dist/handboek-content/whats-new/1.26234.md +1 -0
  6. package/dist/handboek-content/whats-new/1.26237.md +1 -0
  7. package/dist/handboek-content/whats-new/1.26244.md +2 -1
  8. package/dist/handboek-content/whats-new/1.26247.md +88 -0
  9. package/dist/handboek-content/whats-new/whats-new-index.md +1 -0
  10. package/dist/index-store/static-index-worker.js +17 -1
  11. package/dist/index.d.ts +473 -209
  12. package/dist/index.js +6251 -3614
  13. package/dist/memory/embed-worker.js +58 -2
  14. package/dist/memory/image-embed-worker.js +8 -0
  15. package/dist/providers/llama-cpp/gguf-metadata-worker.js +2 -0
  16. package/dist/providers/mlx/python/gezel_mlx_server.py +18 -18
  17. package/dist/ui/assets/AmbientDashboardCard-Cf5fi_fY.js +1 -0
  18. package/dist/ui/assets/{AudioEngineSettings-BDrNIGGm.js → AudioEngineSettings-D3L7HOHe.js} +1 -1
  19. package/dist/ui/assets/{BenchmarksView-CHyujjs8.js → BenchmarksView-B68hrLCl.js} +1 -1
  20. package/dist/ui/assets/CatalogBrowser-DEM9t7Es.js +1 -0
  21. package/dist/ui/assets/{ChannelsSettings-Be_W1mr8.js → ChannelsSettings-DtK_k0Ul.js} +1 -1
  22. package/dist/ui/assets/ChatTimelineView-CQ4Sf4Ip.js +7 -0
  23. package/dist/ui/assets/ConfirmDialog-Dt1ed4Fh.js +1 -0
  24. package/dist/ui/assets/ConnectedAppsPanel-Cl8LEkrt.js +1 -0
  25. package/dist/ui/assets/CraftbookEditor-DEQRlQ2p.js +1 -0
  26. package/dist/ui/assets/{CraftbookScriptEditorView-DXIZYZT3.js → CraftbookScriptEditorView-DhXkkIdK.js} +1 -1
  27. package/dist/ui/assets/{CraftbookTabContent-Bm7t_b37.js → CraftbookTabContent-_oIdpQTG.js} +1 -1
  28. package/dist/ui/assets/{CraftbookToolsetSetup-DTEA-3K3.js → CraftbookToolsetSetup-BKg136L1.js} +1 -1
  29. package/dist/ui/assets/{CraftbooksView-C4X99TTe.js → CraftbooksView-Dm2zH-nW.js} +2 -2
  30. package/dist/ui/assets/{DiffpackReviewView-ClcNxtmF.js → DiffpackReviewView-EFLGJnwr.js} +1 -1
  31. package/dist/ui/assets/DocumentDetail-ClDRj2N-.js +1 -0
  32. package/dist/ui/assets/DocumentsView-ny9oieg2.js +1 -0
  33. package/dist/ui/assets/DropdownMenu-S4d9-3j3.js +1 -0
  34. package/dist/ui/assets/Ds4Settings-CeWlm5Vf.js +1 -0
  35. package/dist/ui/assets/EmbeddedChat-Hjrrgpao.js +1 -0
  36. package/dist/ui/assets/{FaceRecognitionCard-D3hdc7uU.js → FaceRecognitionCard-D7ufKqjI.js} +1 -1
  37. package/dist/ui/assets/FileMapView-DRjf59RH.js +1 -0
  38. package/dist/ui/assets/{FoldersSettings-BcNzl4vT.js → FoldersSettings-DDUhaFio.js} +1 -1
  39. package/dist/ui/assets/GezelDetail-Cph6pVGb.js +1 -0
  40. package/dist/ui/assets/{GezelJsonEditor-fOvYclu9.js → GezelJsonEditor-7vDGyBib.js} +1 -1
  41. package/dist/ui/assets/{GezellenView-BTzhHrxi.js → GezellenView-DQhcO1CP.js} +1 -1
  42. package/dist/ui/assets/{GildeUpdatesCard-Bq6XEpLP.js → GildeUpdatesCard-UKKNm_U8.js} +1 -1
  43. package/dist/ui/assets/{GithubSignInChip-CnlTCG8G.js → GithubSignInChip-DjM3qZsL.js} +1 -1
  44. package/dist/ui/assets/{HandboekMediaProvider-BfQW8_Nr.js → HandboekMediaProvider-DixaXTAH.js} +1 -1
  45. package/dist/ui/assets/HandboekView-BeNQqho9.js +1 -0
  46. package/dist/ui/assets/HistoryView-E2szGNGS.js +1 -0
  47. package/dist/ui/assets/{HomeView-CB_5TJIp.css → HomeView-CNeqCFPc.css} +1 -1
  48. package/dist/ui/assets/HomeView-CkiS3DXy.js +1 -0
  49. package/dist/ui/assets/{ImageEngineSettings-BpMfQy4f.js → ImageEngineSettings-BCKT7Gvi.js} +1 -1
  50. package/dist/ui/assets/{ImageRecognitionSettings-Ct-7-Oas.js → ImageRecognitionSettings-DD6syFez.js} +1 -1
  51. package/dist/ui/assets/IncompleteDownloads-BiPaaahS.js +1 -0
  52. package/dist/ui/assets/InstallProgressRow-DyKOI4MU.js +1 -0
  53. package/dist/ui/assets/KnowledgeCatalogsCard-B132vzRa.js +1 -0
  54. package/dist/ui/assets/KnowledgeView-CtPuIlN4.js +1 -0
  55. package/dist/ui/assets/LlamaCppSettings-D6zHcu4W.js +1 -0
  56. package/dist/ui/assets/{MarkdownField-D-0Zw7gM.js → MarkdownField-CK8K3fzj.js} +1 -1
  57. package/dist/ui/assets/MemoriesTree-DzjXzIrM.js +1 -0
  58. package/dist/ui/assets/{MicrophoneSettings-BIaFxyY_.js → MicrophoneSettings-1FH83SCq.js} +1 -1
  59. package/dist/ui/assets/MlxSettings-BYxUqFnJ.js +1 -0
  60. package/dist/ui/assets/ModelPicker-DoXPfQkQ.js +1 -0
  61. package/dist/ui/assets/{NewScriptDialog-D-gkY8TS.js → NewScriptDialog-C5X-7PMt.js} +1 -1
  62. package/dist/ui/assets/NewTaskDialog-Cyqtmigv.js +2 -0
  63. package/dist/ui/assets/{OllamaSettings-oIE2Mech.js → OllamaSettings-DkjmA-sB.js} +1 -1
  64. package/dist/ui/assets/ProjectChat-YEqUME6k.js +5 -0
  65. package/dist/ui/assets/{ProjectConnectionsTab-BZqp-oKI.js → ProjectConnectionsTab-dFCJpW93.js} +1 -1
  66. package/dist/ui/assets/ProjectGitStatusBar-CjZxG54t.js +1 -0
  67. package/dist/ui/assets/{ProjectGithubView-w8suLCsA.js → ProjectGithubView-CQ4-tmPx.js} +1 -1
  68. package/dist/ui/assets/{ProjectMailTab-DGo7eyB8.js → ProjectMailTab-NaScsZJf.js} +1 -1
  69. package/dist/ui/assets/ProjectOverviewView-ChjxbQas.js +1 -0
  70. package/dist/ui/assets/{ProjectTimeline-DRe3D9qY.js → ProjectTimeline-BZpdCisR.js} +1 -1
  71. package/dist/ui/assets/ProjectsView-J77ECk6V.js +7 -0
  72. package/dist/ui/assets/{RecommendedBadge-BKiDixnB.js → RecommendedBadge-D0m68PAu.js} +1 -1
  73. package/dist/ui/assets/{RemoteServersPanel-DGyl6-Rg.js → RemoteServersPanel-BdLOoORu.js} +1 -1
  74. package/dist/ui/assets/ScriptEditorTabs-BFvIiDFZ.js +2 -0
  75. package/dist/ui/assets/ScriptEditorView-B09rm1vz.js +5 -0
  76. package/dist/ui/assets/{ScriptsView-WQc28TmQ.js → ScriptsView-BvNAJXpo.js} +1 -1
  77. package/dist/ui/assets/{SecurityComplianceSettings-DsMEA4J3.js → SecurityComplianceSettings-DzGOnptO.js} +1 -1
  78. package/dist/ui/assets/SessionSwitcher-6okzcxT7.js +1 -0
  79. package/dist/ui/assets/SettingsView-Dur4dLhW.js +3 -0
  80. package/dist/ui/assets/SquisqIntegration-6v3yNOIP.js +2 -0
  81. package/dist/ui/assets/{StorageCleanupDialog-DHqwyMZZ.js → StorageCleanupDialog-OQlomMJD.js} +1 -1
  82. package/dist/ui/assets/{StorageUsageCard-CdT6SU51.js → StorageUsageCard-f6c6qTbM.js} +1 -1
  83. package/dist/ui/assets/Tabs-jE0Z5Tzd.js +1 -0
  84. package/dist/ui/assets/TaskTabContent-0w3kAUWR.js +1 -0
  85. package/dist/ui/assets/TasksView-BVMT4BAY.js +1 -0
  86. package/dist/ui/assets/{TerminalCodeEditor-77pBm6f3.js → TerminalCodeEditor-DO7zLKy-.js} +2 -2
  87. package/dist/ui/assets/ToolsetsEditor-Bb1wD5mV.js +8 -0
  88. package/dist/ui/assets/TransformToolbarButton-BWYkEB0d.js +5 -0
  89. package/dist/ui/assets/UnrecognizedModels-HtdMZUqK.js +1 -0
  90. package/dist/ui/assets/{VideoEngineSettings-DzMeINuv.js → VideoEngineSettings-Dq8Nw_tK.js} +1 -1
  91. package/dist/ui/assets/{WorkspaceIndexPane-DU4yd4Ai.js → WorkspaceIndexPane-fpDz4MwZ.js} +1 -1
  92. package/dist/ui/assets/{api-BX5xXiFs.js → api-BPraLwsh.js} +1 -1
  93. package/dist/ui/assets/chat-thread-memory-Be48zsyG.js +1 -0
  94. package/dist/ui/assets/chunk-6ECMNUIP-DDVjPyfK.js +15 -0
  95. package/dist/ui/assets/{chunk-6N2J7C2B-B5QIrD9m.js → chunk-6N2J7C2B-CsppiLVr.js} +1 -1
  96. package/dist/ui/assets/{chunk-A6N6IN3I-DXok09eC.js → chunk-A6N6IN3I-ofeM4l8g.js} +1 -1
  97. package/dist/ui/assets/chunk-B7GEAZBI-Divd2h1k.js +1 -0
  98. package/dist/ui/assets/chunk-DXYWKZ52-BXcAlClu.js +1 -0
  99. package/dist/ui/assets/chunk-FLR2ARKC-D7wrvQgT.js +2 -0
  100. package/dist/ui/assets/chunk-IIQYS2YH-DKZhWMpn.js +1 -0
  101. package/dist/ui/assets/{chunk-ILCJ3WFD-WRukZ7R1.js → chunk-ILCJ3WFD-CLZxw4Ge.js} +3 -3
  102. package/dist/ui/assets/chunk-OBADJV7C-CDVOcmYt.js +1 -0
  103. package/dist/ui/assets/chunk-Q77KNJIN-BIDRf0aP.js +6 -0
  104. package/dist/ui/assets/chunk-S5PCVMKU-Df5XzhSE.js +6 -0
  105. package/dist/ui/assets/chunk-UBFT2CDQ-FexGDigd.js +31 -0
  106. package/dist/ui/assets/{chunk-USU6HTKB-D5FmDzJU.js → chunk-USU6HTKB-B_p-YcDp.js} +1 -1
  107. package/dist/ui/assets/chunk-VKXOZTYP-BoVvWSBR.js +5 -0
  108. package/dist/ui/assets/{chunk-6RQOV3B3-CwvKotJw.js → chunk-VPWPEMZJ-DRKoa_j0.js} +1 -1
  109. package/dist/ui/assets/{chunk-WATAOG4Y-DXg2lov5.js → chunk-WATAOG4Y-C1EXVPmG.js} +1 -1
  110. package/dist/ui/assets/{container-B7jJtK5V.js → container-Ce94efbg.js} +1 -1
  111. package/dist/ui/assets/csv-62UGQMzZ.js +1 -0
  112. package/dist/ui/assets/data-B2kHjlc5.js +1 -0
  113. package/dist/ui/assets/dist-B9-VrAP8.js +2 -0
  114. package/dist/ui/assets/dist-BaHut5iX.js +2 -0
  115. package/dist/ui/assets/dist-BqGwkOe5.js +225 -0
  116. package/dist/ui/assets/dist-ZnIgkoEi.js +4 -0
  117. package/dist/ui/assets/{dist-BHl1ZAVG.js → dist-l6uUFZMV.js} +2 -2
  118. package/dist/ui/assets/dist-pLLFUPO-.js +1 -0
  119. package/dist/ui/assets/{doc-s6H7T0IO.js → doc-Dr5K49bx.js} +28 -28
  120. package/dist/ui/assets/document-companion-BQk2kS0F.js +1 -0
  121. package/dist/ui/assets/document-import-QoM9UxJr.js +1 -0
  122. package/dist/ui/assets/docx-sXa1Rf41.js +2 -0
  123. package/dist/ui/assets/{epub-B98SgHBz.js → epub-RopMP0ec.js} +4 -4
  124. package/dist/ui/assets/{export-options-Bu-tI6og.js → export-options-f7PKjEBb.js} +1 -1
  125. package/dist/ui/assets/extract-UTAOG7LV-4WDRw1o4.js +1 -0
  126. package/dist/ui/assets/file-browser-c2tf4MIb.js +5 -0
  127. package/dist/ui/assets/html-BGVOMhkv.js +253 -0
  128. package/dist/ui/assets/icons-DWaUNQbT.js +1 -0
  129. package/dist/ui/assets/images-JLBFCDD4-6JitW0hD.js +1 -0
  130. package/dist/ui/assets/index-B8NcxqcR.css +1 -0
  131. package/dist/ui/assets/index-C0DYtvfg.js +34 -0
  132. package/dist/ui/assets/index-J8TOMdvV.js +2 -0
  133. package/dist/ui/assets/{infer-kCLH1C8z.js → infer-LEGOsu64.js} +2 -2
  134. package/dist/ui/assets/ironcalc-BAi5gOlE.js +3 -0
  135. package/dist/ui/assets/layouts-2A7QNF6Y-CVwP7noP.js +1 -0
  136. package/dist/ui/assets/{mail-link-CI6YD6k2.js → mail-link-DXkmCd5b.js} +1 -1
  137. package/dist/ui/assets/markdown-baseline-9B52XlX2.js +1 -0
  138. package/dist/ui/assets/{markdown-Bi9b5f5Y.js → markdown-ryKA_OmY.js} +1 -1
  139. package/dist/ui/assets/materialize-A34OZGEU-xNNKzytx.js +1 -0
  140. package/dist/ui/assets/model-inventory-ykSm_IT5.js +1 -0
  141. package/dist/ui/assets/{model-quantization-BDzrELN_.js → model-quantization-CLO7XLoF.js} +1 -1
  142. package/dist/ui/assets/{monaco-base-BiVSa1J-.js → monaco-base-B1H1U1Sw.js} +1 -1
  143. package/dist/ui/assets/{monaco-setup-UeltVkg_.js → monaco-setup-DjhrGQui.js} +1 -1
  144. package/dist/ui/assets/{new-project-meta-0xhggGA_.js → new-project-meta-_f9sfcRX.js} +1 -1
  145. package/dist/ui/assets/outside-in-D73N1g_b.js +3 -0
  146. package/dist/ui/assets/{pdf-DgTjy3rN.js → pdf-BOjVDlCK.js} +3 -3
  147. package/dist/ui/assets/{pending-drafts-YVW6X55O.js → pending-drafts-B11MKQ9R.js} +1 -1
  148. package/dist/ui/assets/{poppetje-Ce-02Aqi.js → poppetje-DLB8uevw.js} +2 -2
  149. package/dist/ui/assets/pptx-BuxyNxQh.js +6 -0
  150. package/dist/ui/assets/primitives-CWrGZpPI.js +41 -0
  151. package/dist/ui/assets/run-export-ChaMXrKS.js +23 -0
  152. package/dist/ui/assets/squisq-formats-aAdypXoy.js +1 -0
  153. package/dist/ui/assets/standalone-source-q_Zzd1bd.js +11 -0
  154. package/dist/ui/assets/storage-D8pE2zg0.js +1 -0
  155. package/dist/ui/assets/styles-BhnF3s2q.css +1 -0
  156. package/dist/ui/assets/styles-CKVKwqoQ.js +550 -0
  157. package/dist/ui/assets/table-fcouR4db.js +1 -0
  158. package/dist/ui/assets/{terminal-monaco-setup-DNoK2tN4.js → terminal-monaco-setup-BAzrVzeR.js} +1 -1
  159. package/dist/ui/assets/{useCompactLayout-BarJPYcv.js → useCompactLayout-Dtolvzye.js} +0 -0
  160. package/dist/ui/assets/{useCopilotAvailability-BH1nLXQI.js → useCopilotAvailability-3xZvKgTF.js} +1 -1
  161. package/dist/ui/assets/{useDiffpacks-CK8W_OD_.js → useDiffpacks-Dsnr0wtX.js} +1 -1
  162. package/dist/ui/assets/{useGitSync-DWxX5-7K.js → useGitSync-BCTptQsp.js} +1 -1
  163. package/dist/ui/assets/{useShowWorkInProgressFeatures-DwwviLRO.js → useShowWorkInProgressFeatures-BhDNuQiU.js} +1 -1
  164. package/dist/ui/assets/{useTotalRamBytes-WoN_mi-V.js → useTotalRamBytes-DIx-_pf8.js} +1 -1
  165. package/dist/ui/assets/wasm-DdxEDD2H.js +1 -0
  166. package/dist/ui/assets/wasm_bg-DW9Xt_vt.wasm +0 -0
  167. package/dist/ui/assets/xlsx-DyBGuAO1.js +4 -0
  168. package/dist/ui/index.html +19 -18
  169. package/package.json +11 -11
  170. package/dist/ui/assets/AmbientDashboardCard-C1Ee-FKZ.js +0 -1
  171. package/dist/ui/assets/CatalogBrowser-Bz8ZtxPn.js +0 -1
  172. package/dist/ui/assets/ChatTimelineView-Do9EryEH.js +0 -7
  173. package/dist/ui/assets/ConfirmDialog-BHFs6vmJ.js +0 -1
  174. package/dist/ui/assets/ConnectedAppsPanel-BtMayq0R.js +0 -1
  175. package/dist/ui/assets/CraftbookEditor-D5jTzWwF.js +0 -1
  176. package/dist/ui/assets/DocumentDetail-CPU51d04.js +0 -1
  177. package/dist/ui/assets/DocumentsView-B6OyjvJ0.js +0 -1
  178. package/dist/ui/assets/DropdownMenu-D5fCzIrh.js +0 -1
  179. package/dist/ui/assets/Ds4Settings-CrUM_KGP.js +0 -1
  180. package/dist/ui/assets/EmbeddedChat-ue9ia-WY.js +0 -1
  181. package/dist/ui/assets/FileMapView-CxvfDLGA.js +0 -1
  182. package/dist/ui/assets/GezelDetail-DHuqBK55.js +0 -1
  183. package/dist/ui/assets/HandboekView-CPnnyj29.js +0 -1
  184. package/dist/ui/assets/HistoryView-B4VAfEMe.js +0 -1
  185. package/dist/ui/assets/HomeView-ccH60J6f.js +0 -1
  186. package/dist/ui/assets/KnowledgeCatalogsCard-Bi5Rx9Iz.js +0 -1
  187. package/dist/ui/assets/KnowledgeView-DAwjwLZo.js +0 -1
  188. package/dist/ui/assets/LlamaCppSettings-Ceyk9pDP.js +0 -1
  189. package/dist/ui/assets/MemoriesTree-BKZEPJpm.js +0 -1
  190. package/dist/ui/assets/MlxSettings-CG3wfuc3.js +0 -1
  191. package/dist/ui/assets/ModelPicker-CCBVjLMS.js +0 -1
  192. package/dist/ui/assets/NewPathDialog-D4jnNBfP.js +0 -1
  193. package/dist/ui/assets/NewTaskDialog-Ox9D612Z.js +0 -2
  194. package/dist/ui/assets/ProjectChat-DMwKnkW-.js +0 -5
  195. package/dist/ui/assets/ProjectGitStatusBar-C6bkCSby.js +0 -1
  196. package/dist/ui/assets/ProjectOverviewView-NNwXd_QQ.js +0 -1
  197. package/dist/ui/assets/ProjectsView-SBPgYOq8.js +0 -7
  198. package/dist/ui/assets/ScriptEditorTabs-paocQ6dj.js +0 -2
  199. package/dist/ui/assets/ScriptEditorView-N9zSLqqi.js +0 -5
  200. package/dist/ui/assets/SessionSwitcher-C8te7YSe.js +0 -1
  201. package/dist/ui/assets/SettingsView-Brl4JQkW.js +0 -3
  202. package/dist/ui/assets/Tabs-BAY1Q79B.js +0 -1
  203. package/dist/ui/assets/TaskTabContent-CNPJ4DQj.js +0 -1
  204. package/dist/ui/assets/TasksView-DuMjFS8S.js +0 -1
  205. package/dist/ui/assets/ToolsetsEditor-BdxHnIBj.js +0 -8
  206. package/dist/ui/assets/TransformToolbarButton-CVg5nz36.js +0 -5
  207. package/dist/ui/assets/UnrecognizedModels-Cw9Ku_bW.js +0 -1
  208. package/dist/ui/assets/chat-thread-memory-CZGcwgGo.js +0 -1
  209. package/dist/ui/assets/chunk-6ECMNUIP-C1kohb1U.js +0 -15
  210. package/dist/ui/assets/chunk-AONELFLA-Cv2nS9ga.js +0 -1
  211. package/dist/ui/assets/chunk-IIQYS2YH-Dxg6MAfT.js +0 -1
  212. package/dist/ui/assets/chunk-MIKKUKOD-XIkmalSN.js +0 -31
  213. package/dist/ui/assets/chunk-NNJLSQPW-DJA6camf.js +0 -5
  214. package/dist/ui/assets/chunk-S5PCVMKU-DbCZ5AUH.js +0 -6
  215. package/dist/ui/assets/csv-xmd1_Aqd.js +0 -4
  216. package/dist/ui/assets/dist-BPx-FyRH.js +0 -222
  217. package/dist/ui/assets/dist-Bvo52IGx.js +0 -1
  218. package/dist/ui/assets/dist-D5aoNQwk.js +0 -2
  219. package/dist/ui/assets/docx-Cj4A9MhC.js +0 -2
  220. package/dist/ui/assets/extract-UTAOG7LV-C4b7ycaL.js +0 -1
  221. package/dist/ui/assets/file-browser-80qWoVju.js +0 -5
  222. package/dist/ui/assets/html-C9TlzI57.js +0 -253
  223. package/dist/ui/assets/icons-C9dD-bDi.js +0 -1
  224. package/dist/ui/assets/images-ESPQKVTW-D7SgdVJ_.js +0 -1
  225. package/dist/ui/assets/index-D1m4Wx8V.css +0 -1
  226. package/dist/ui/assets/index-DXWR4qW1.js +0 -34
  227. package/dist/ui/assets/layouts-2A7QNF6Y-De2t-YXl.js +0 -1
  228. package/dist/ui/assets/markdown-baseline-HMqF2ChK.js +0 -1
  229. package/dist/ui/assets/outside-in-BFVUUcLa.js +0 -3
  230. package/dist/ui/assets/pptx-6ChgUEf4.js +0 -6
  231. package/dist/ui/assets/primitives-DEsn1shf.js +0 -41
  232. package/dist/ui/assets/run-export-BrYhHj1O.js +0 -23
  233. package/dist/ui/assets/standalone-source-D6mbpa3h.js +0 -11
  234. package/dist/ui/assets/storage-fn4FCEVK.js +0 -1
  235. package/dist/ui/assets/styles-C0EoNJbk.css +0 -1
  236. package/dist/ui/assets/styles-CKr_yrbn.js +0 -541
  237. package/dist/ui/assets/xlsx-DH7sTb3W.js +0 -4
@@ -1 +1 @@
1
- import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{n as t,t as n}from"./jsx-runtime-CEpd2cAX.js";import{F as r,I as i,M as a,N as o,P as s,j as c}from"./primitives-DEsn1shf.js";import{Nt as l}from"./dist-BPx-FyRH.js";import{t as u}from"./api-BX5xXiFs.js";import{t as d}from"./ConfirmDialog-BHFs6vmJ.js";import{t as f}from"./CatalogBrowser-Bz8ZtxPn.js";import{t as p}from"./LicenseButton-D3VmcVG1.js";var m=e(t(),1),h=n(),g=`image-generator`,_=`generate_image`;function v(){let[e,t]=(0,m.useState)([]),[n,r]=(0,m.useState)(!0),[i,a]=(0,m.useState)(!1),o=(0,m.useCallback)(async()=>{r(!0);try{let e=await u.listGezels();t(e.gezels)}catch{}finally{r(!1)}},[]);(0,m.useEffect)(()=>{o();let e=()=>void o();return window.addEventListener(`gezel:gezel-updated`,e),()=>window.removeEventListener(`gezel:gezel-updated`,e)},[o]);let s=(0,m.useMemo)(()=>e.filter(e=>e.fixedFunction?.tool===_),[e]),c=(0,m.useCallback)(e=>{window.dispatchEvent(new CustomEvent(`gezel:open-tab`,{detail:{kind:`gezel`,id:e,activate:!0}}))},[]),l=(0,m.useCallback)(e=>{a(!1),o(),c(e.id)},[o,c]);return n?null:(0,h.jsxs)(`div`,{className:`ff-img-hint`,children:[s.length>0?(0,h.jsxs)(`div`,{className:`ff-img-hint-have`,children:[(0,h.jsx)(`span`,{className:`muted small`,children:`Image-generator gezel`}),s.length===1?(0,h.jsx)(`button`,{type:`button`,className:`link-btn`,onClick:()=>c(s[0].id),title:`Open ${s[0].name}`,children:s[0].name}):(0,h.jsx)(`span`,{children:s.map((e,t)=>(0,h.jsxs)(`span`,{children:[(0,h.jsx)(`button`,{type:`button`,className:`link-btn`,onClick:()=>c(e.id),title:`Open ${e.name}`,children:e.name}),t<s.length-1&&(0,h.jsx)(`span`,{className:`muted`,children:`, `})]},e.id))}),(0,h.jsx)(`span`,{className:`muted small`,children:`— @-mention them in chat to generate.`})]}):(0,h.jsxs)(`div`,{className:`ff-img-hint-empty`,children:[(0,h.jsxs)(`p`,{className:`muted small`,children:[`Once an engine is set up, the easiest way to use it from chat is to add an`,` `,(0,h.jsx)(`strong`,{children:`image-generator gezel`}),`. They forward your @-mention text straight to`,` `,(0,h.jsx)(`code`,{children:_}),` — no LLM in the middle.`]}),(0,h.jsx)(`button`,{type:`button`,className:`primary`,onClick:()=>a(!0),children:`Add an image-generator gezel`})]}),(0,h.jsx)(y,{open:i,onClose:()=>a(!1),onCreated:l})]})}function y({open:e,onClose:t,onCreated:n}){let[d,f]=(0,m.useState)(()=>l()),[p,v]=(0,m.useState)(null),[y,b]=(0,m.useState)(!1),[x,S]=(0,m.useState)(null),[C,w]=(0,m.useState)(!1),T=(0,m.useRef)(!1);(0,m.useEffect)(()=>{!e||T.current||(T.current=!0,w(!0),u.getCatalogItem(`gezel-template`,g).then(e=>{e.manifest.kind===`gezel-template`&&v(e.manifest.description)}).catch(e=>{S(e instanceof Error?e.message:String(e))}).finally(()=>w(!1)))},[e]),(0,m.useEffect)(()=>{e&&(f(l()),S(null),b(!1))},[e]);let E=()=>f(l()),D=(0,m.useCallback)(async()=>{if(d.trim()){b(!0),S(null);try{n(await u.createGezelFromTemplate(g,{name:d.trim()}))}catch(e){S(e instanceof Error?e.message:String(e))}finally{b(!1)}}},[d,n]);return(0,h.jsx)(r,{open:e,onOpenChange:e=>{!e&&!y&&t()},children:(0,h.jsxs)(s,{children:[(0,h.jsx)(o,{}),(0,h.jsxs)(c,{className:`template-picker-dialog`,children:[(0,h.jsxs)(`header`,{style:{display:`flex`,justifyContent:`space-between`,alignItems:`baseline`},children:[(0,h.jsx)(i,{asChild:!0,children:(0,h.jsx)(`h3`,{style:{margin:0},children:`Add an image-generator gezel`})}),(0,h.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:t,disabled:y,children:`Cancel`})]}),(0,h.jsxs)(a,{className:`muted small`,style:{margin:`0.25rem 0 0.5rem 0`},children:[`Forwards your @-mention text straight to `,(0,h.jsx)(`code`,{children:_}),`. No LLM is invoked.`]}),C&&(0,h.jsx)(`p`,{className:`muted small`,children:`Loading template…`}),p&&(0,h.jsx)(`p`,{className:`muted small`,children:p}),(0,h.jsx)(`form`,{onSubmit:e=>{e.preventDefault(),D()},style:{marginTop:`0.5rem`,padding:`0.6rem`,background:`rgba(79, 125, 255, 0.06)`,borderRadius:`6px`,display:`flex`,flexDirection:`column`,gap:`0.5rem`},children:(0,h.jsxs)(`div`,{style:{display:`flex`,gap:`0.5rem`,alignItems:`center`},children:[(0,h.jsx)(`span`,{className:`muted small`,style:{flexShrink:0},children:`Name:`}),(0,h.jsx)(`input`,{value:d,onChange:e=>f(e.target.value),disabled:y,style:{flex:1}}),(0,h.jsx)(`button`,{type:`button`,className:`dice-btn`,onClick:E,disabled:y,title:`Pick a random name`,"aria-label":`Pick a random name`,children:`🎲`}),(0,h.jsx)(`button`,{type:`submit`,className:`primary`,disabled:y||!d.trim(),children:y?`Creating…`:`Create`})]})}),x&&(0,h.jsx)(`p`,{className:`error`,children:x})]})]})})}function b(e){return e>=1024**3?`${(e/1024**3).toFixed(1)} GB`:e>=1024**2?`${(e/1024**2).toFixed(0)} MB`:e>=1024?`${(e/1024).toFixed(0)} KB`:`${e} B`}function x(e,t){switch(e){case`low`:return`Runs on ${t} GB`;case`mid`:return`${t} GB+`;case`high`:return`${t} GB+ recommended`;case`workstation`:return`${t} GB+ workstation`}}function S({disabledReason:e,onModelsChanged:t,configuredDefaultModelId:n,onSetActiveModel:r}){let[i,a]=(0,m.useState)([]),[o,s]=(0,m.useState)(null),[c,l]=(0,m.useState)(new Map),[g,_]=(0,m.useState)(null),v=(0,m.useRef)(c);v.current=c;let y=(0,m.useCallback)(async()=>{try{let e=await u.listInstalledImageModels();a(e.models),s(null)}catch(e){a([]),s(e.message)}},[]),S=(0,m.useCallback)((e,n)=>{let r=new AbortController;l(t=>{let n=new Map(t),i=n.get(e);return n.set(e,{...i??{id:e,bytesWritten:0,totalBytes:0},controller:r}),n}),n(n=>{n.type===`progress`?l(t=>{let r=new Map(t),i=r.get(e);if(!i)return t;let{retrying:a,...o}=i;return r.set(e,{...o,bytesWritten:n.bytesWritten,totalBytes:n.totalBytes??i.totalBytes}),r}):n.type===`retrying`?l(t=>{let r=new Map(t),i=r.get(e);return i?(r.set(e,{...i,retrying:{attempt:n.attempt,maxAttempts:n.maxAttempts,delayMs:n.delayMs,reason:n.reason}}),r):t}):n.type===`error`?l(t=>{let r=new Map(t),i=r.get(e);return i&&r.set(e,{...i,error:n.error,retrying:void 0}),r}):n.type===`done`&&setTimeout(()=>{l(t=>{let n=new Map(t);return n.delete(e),n}),y(),t?.()},800)},r.signal).catch(t=>{r.signal.aborted||l(n=>{let r=new Map(n),i=r.get(e);return i&&r.set(e,{...i,error:t.message}),r})})},[y,t]);(0,m.useEffect)(()=>{y();let e=!1;return u.listActiveImagePulls().then(({pulls:t})=>{if(!e)for(let e of t)e.finished||(l(t=>{if(t.has(e.id))return t;let n=new Map(t);return n.set(e.id,{id:e.id,bytesWritten:e.bytesWritten,totalBytes:e.totalBytes,controller:new AbortController,...e.retrying?{retrying:e.retrying}:{},...e.error?{error:e.error}:{}}),n}),S(e.id,(t,n)=>u.subscribeImagePull(e.id,t,n)))}).catch(()=>{}),()=>{e=!0}},[y,S]);let w=(0,m.useCallback)(e=>{v.current.has(e)||S(e,(t,n)=>u.pullImageModel(e,t,n))},[S]),T=(0,m.useCallback)(e=>{v.current.get(e)?.controller.abort(),l(t=>{let n=new Map(t);return n.delete(e),n}),S(e,(t,n)=>u.pullImageModel(e,t,n))},[S]),E=(0,m.useCallback)(e=>{v.current.get(e)?.controller.abort(),l(t=>{let n=new Map(t);return n.delete(e),n}),u.cancelImagePull(e).catch(()=>{})},[]),D=(0,m.useCallback)(async()=>{if(g)try{await u.deleteImageModel(g),await y(),t?.()}catch(e){s(e.message)}finally{_(null)}},[g,y,t]),O=(0,m.useMemo)(()=>new Set(i.map(e=>e.id)),[i]),k=!!r&&i.length>0,A=n&&O.has(n)?n:i[0]?.id;return(0,h.jsxs)(`div`,{className:`ollama-model-manager`,children:[c.size>0&&(0,h.jsxs)(`div`,{className:`ollama-section`,children:[(0,h.jsx)(`h4`,{children:`Downloading…`}),(0,h.jsx)(`div`,{className:`ollama-pull-list`,children:Array.from(c.values()).map(e=>(0,h.jsx)(C,{pull:e,onCancel:()=>E(e.id),onRetry:()=>T(e.id)},e.id))})]}),(i.length>0||o)&&(0,h.jsxs)(`div`,{className:`ollama-section`,children:[(0,h.jsx)(`h4`,{children:`Local models`}),o&&(0,h.jsx)(`p`,{className:`error`,children:o}),k&&i.length>1&&(0,h.jsxs)(`p`,{className:`muted small`,children:[`The `,(0,h.jsx)(`strong`,{children:`active`}),` model is what the image-generator gezel and the`,` `,(0,h.jsx)(`code`,{children:`render_image`}),` tool use by default. A gezel can still ask for a specific model per image; switching reloads the engine, which takes a moment.`]}),i.length>0&&(0,h.jsxs)(`table`,{className:`ollama-model-table`,children:[(0,h.jsx)(`thead`,{children:(0,h.jsxs)(`tr`,{children:[k&&(0,h.jsx)(`th`,{scope:`col`,className:`gz-active-model-column`,children:`Active`}),(0,h.jsx)(`th`,{children:`Name`}),(0,h.jsx)(`th`,{children:`Size`}),(0,h.jsx)(`th`,{children:`Added`}),(0,h.jsx)(`th`,{})]})}),(0,h.jsx)(`tbody`,{children:i.map(e=>(0,h.jsxs)(`tr`,{children:[k&&(0,h.jsx)(`td`,{className:`gz-active-model-column`,children:(0,h.jsx)(`input`,{type:`radio`,name:`active-image-model`,className:`gz-active-model-radio`,"aria-label":`Use ${e.id} as the active image model`,checked:A===e.id,onChange:()=>{A!==e.id&&r?.(e.id)}})}),(0,h.jsxs)(`td`,{children:[(0,h.jsx)(`code`,{children:e.id}),(0,h.jsx)(`div`,{className:`muted small`,children:e.name})]}),(0,h.jsx)(`td`,{children:b(e.approxSizeBytes)}),(0,h.jsx)(`td`,{className:`muted small`,children:new Date(e.installedAt).toLocaleDateString()}),(0,h.jsx)(`td`,{children:(0,h.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:()=>_(e.id),children:`Delete`})})]},e.id))})]})]}),(0,h.jsxs)(`div`,{className:`ollama-section ollama-section--flat ollama-section--download`,children:[(0,h.jsx)(`h4`,{children:`Download a model`}),(0,h.jsx)(f,{kind:`image-model`,emptyMessage:`No image models in the catalog yet. Remote catalog sources can add entries without an app update.`,action:t=>{if(t.manifest.kind!==`image-model`)return null;let n=t.manifest,r=O.has(n.id),i=c.get(n.id),a=!!i,o=i&&i.totalBytes>0?Math.min(100,Math.round(i.bytesWritten/i.totalBytes*100)):null;return(0,h.jsxs)(`div`,{className:`catalog-ollama-action`,children:[(0,h.jsxs)(`div`,{className:`catalog-ollama-meta`,children:[(0,h.jsxs)(`div`,{className:`catalog-ollama-specs muted small`,children:[(0,h.jsx)(`code`,{children:n.id}),(0,h.jsx)(`span`,{children:`·`}),(0,h.jsx)(`span`,{children:b(n.approxSizeBytes)}),n.quantization&&(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{children:`·`}),(0,h.jsx)(`span`,{children:n.quantization})]}),(0,h.jsx)(`span`,{children:`·`}),(0,h.jsx)(`span`,{children:x(n.hardwareTier,n.minRamGB)})]}),(0,h.jsx)(`div`,{className:`catalog-ollama-pills`,children:(0,h.jsx)(p,{manifest:n})})]}),(0,h.jsx)(`button`,{type:`button`,disabled:r||a||!!e,title:e??void 0,onClick:()=>void w(n.id),children:r?`On device`:a?o===null?`Downloading…`:`Downloading… ${o}%`:`Download`})]})}})]}),(0,h.jsx)(d,{open:g!==null,title:`Delete image model?`,message:g?`"${g}" will be removed from local storage. This frees disk space; download it again later to use it.`:``,confirmLabel:`Delete`,danger:!0,onCancel:()=>_(null),onConfirm:D})]})}function C({pull:e,onCancel:t,onRetry:n}){let r=e.totalBytes>0,i=r?Math.min(100,Math.round(e.bytesWritten/e.totalBytes*100)):0,a;if(e.error)a=e.error;else if(e.retrying){let t=Math.max(1,Math.round(e.retrying.delayMs/1e3));a=`${e.retrying.reason} — retrying in ${t}s (attempt ${e.retrying.attempt}/${e.retrying.maxAttempts})`}else a=r?`Downloading… (${b(e.bytesWritten)} of ${b(e.totalBytes)}, ${i}%)`:e.bytesWritten>0?`Downloading… (${b(e.bytesWritten)})`:`Preparing download…`;return(0,h.jsxs)(`div`,{className:`ollama-pull${e.error?` ollama-pull-error`:e.retrying?` ollama-pull-warning`:``}`,children:[(0,h.jsxs)(`div`,{className:`ollama-pull-head`,children:[(0,h.jsx)(`code`,{children:e.id}),(0,h.jsx)(`span`,{className:`muted small`,children:a}),e.error?(0,h.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:n,children:`Retry`}):(0,h.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:t,children:`Cancel`})]}),r?(0,h.jsxs)(`div`,{className:`ollama-pull-bar`,children:[(0,h.jsx)(`div`,{className:`ollama-pull-bar-fill`,style:{width:`${i}%`}}),(0,h.jsxs)(`span`,{className:`ollama-pull-bar-label`,children:[i,`%`]})]}):(0,h.jsx)(`div`,{className:`ollama-pull-bar ollama-pull-bar-indeterminate`,children:(0,h.jsx)(`div`,{className:`ollama-pull-bar-fill`})})]})}function w({onModelsChanged:e}){let[t,n]=(0,m.useState)({kind:`idle`}),[r,i]=(0,m.useState)(0),[a,o]=(0,m.useState)(null),[s,c]=(0,m.useState)(``),[l,d]=(0,m.useState)(null),f=(0,m.useCallback)(async()=>{n({kind:`probing`});try{let[e,t]=await Promise.all([u.getImageEngineStatus(),u.getConfig()]);o(t),e.engine.status===`not-configured`?n({kind:`engine-not-configured`,status:e}):e.engine.status===`unreachable`?n({kind:`engine-unreachable`,status:e}):e.modelCount===0?n({kind:`no-models`,status:e}):n({kind:`ready`,status:e})}catch(e){n({kind:`probe-failed`,error:e.message})}},[]);(0,m.useEffect)(()=>{f()},[f,r]);let p=t.kind===`engine-not-configured`||t.kind===`engine-unreachable`||t.kind===`probe-failed`,g=a?.imageProvider??`sd-cpp`,_=`status`in t?t.status.engine.kind??`local`:`local`,y=g===`google-ai`||g===`openai`,b=(0,m.useCallback)(async e=>{d(`switching engine…`);try{let t=await u.updateConfig({imageProvider:e});o(t),c(``),d(null),i(e=>e+1)}catch(e){d(`switch failed: ${e.message}`)}},[]),x=(0,m.useCallback)(async()=>{if(s.trim()){d(`saving key…`);try{let e=g===`google-ai`?{googleAiApiKey:s.trim()}:g===`openai`?{openaiApiKey:s.trim()}:{},t=await u.updateConfig(e);o(t),c(``),d(`key saved`),i(e=>e+1)}catch(e){d(`save failed: ${e.message}`)}}},[s,g]),C=(0,m.useCallback)(async()=>{d(`clearing key…`);try{let e=g===`google-ai`?{googleAiApiKey:``}:g===`openai`?{openaiApiKey:``}:{},t=await u.updateConfig(e);o(t),c(``),d(`key cleared`),i(e=>e+1)}catch(e){d(`clear failed: ${e.message}`)}},[g]),w=(0,m.useCallback)(async e=>{d(`saving…`);try{let t=await u.updateConfig({defaultImageModel:{...a?.defaultImageModel,"sd-cpp":e}});o(t),d(null)}catch(e){d(`save failed: ${e.message}`)}},[a?.defaultImageModel]),O=(0,m.useCallback)(async e=>{d(`saving…`);try{let t=await u.updateConfig({imageGenerationConfirmation:e});o(t),d(null)}catch(e){d(`save failed: ${e.message}`)}},[]),k=E(a?.imageGenerationConfirmation);return(0,h.jsxs)(`div`,{className:`provider-card`,children:[(0,h.jsxs)(`div`,{className:`settings-card-header`,children:[(0,h.jsx)(`h3`,{children:`Image generation`}),(0,h.jsx)(D,{probe:t})]}),(0,h.jsx)(v,{}),(0,h.jsxs)(`label`,{className:`provider-row`,children:[(0,h.jsx)(`span`,{children:`Engine`}),(0,h.jsxs)(`select`,{value:g,onChange:e=>void b(e.target.value),children:[(0,h.jsx)(`option`,{value:`sd-cpp`,children:`Local (Stable Diffusion)`}),(0,h.jsx)(`option`,{value:`google-ai`,children:`Google Nano Banana 2 (cloud)`}),(0,h.jsx)(`option`,{value:`openai`,children:`OpenAI GPT Image 2 (cloud)`})]})]}),g===`sd-cpp`&&(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`p`,{className:`muted small`,children:`Generate images locally through the bundled Stable Diffusion engine.`}),t.kind===`engine-not-configured`&&(0,h.jsxs)(`p`,{className:`error`,children:[`The image engine isn't wired up on this install. Models on disk can't run on their own — they need the `,(0,h.jsx)(`code`,{children:`sd-server`}),` binary or an external server. Set`,` `,(0,h.jsx)(`code`,{children:`GEZEL_SD_SERVER_URL`}),` to point at a running sd-server, or build the bundled binary at`,` `,(0,h.jsxs)(`code`,{children:[`native/build/`,`<`,`platform`,`>`,`/sd-server`]}),`.`,t.status.engine.error&&(0,h.jsxs)(h.Fragment,{children:[` `,(0,h.jsxs)(`span`,{className:`muted small`,children:[`Details: `,t.status.engine.error]})]})]}),t.kind===`engine-unreachable`&&(0,h.jsxs)(`p`,{className:`error`,children:[`The image engine is configured but isn't responding at`,` `,(0,h.jsx)(`code`,{children:t.status.engine.baseUrl}),`. Check whether `,(0,h.jsx)(`code`,{children:`sd-server`}),` is running.`,t.status.engine.error&&(0,h.jsxs)(h.Fragment,{children:[` `,(0,h.jsxs)(`span`,{className:`muted small`,children:[`Details: `,t.status.engine.error]})]})]}),t.kind===`probe-failed`&&(0,h.jsxs)(`p`,{className:`error`,children:[`Couldn't reach the Gezel service. Details: `,t.error]}),(0,h.jsx)(S,{...p?{disabledReason:t.kind===`engine-not-configured`?`Image engine is not configured — downloading a model now would still leave it unrunnable.`:`Image engine is not reachable.`}:{},...a?.defaultImageModel?.[`sd-cpp`]?{configuredDefaultModelId:a.defaultImageModel[`sd-cpp`]}:{},onSetActiveModel:w,onModelsChanged:()=>{i(e=>e+1),e?.()}})]}),g===`google-ai`&&(0,h.jsx)(T,{providerLabel:`Google Nano Banana 2`,modelId:`gemini-3.1-flash-image-preview`,docsHref:`https://ai.google.dev/gemini-api/docs/image-generation`,hasKey:a?.hasGoogleAiApiKey===!0,maskedKey:a?.googleAiApiKey,keyPlaceholder:`AIza…`,keyDraft:s,onKeyDraftChange:c,onSaveKey:x,onClearKey:C,probe:t}),g===`openai`&&(0,h.jsx)(T,{providerLabel:`OpenAI GPT Image 2`,modelId:`gpt-image-2`,docsHref:`https://developers.openai.com/api/docs/models/gpt-image-2`,hasKey:a?.hasOpenaiApiKey===!0,maskedKey:a?.openaiApiKey,keyPlaceholder:`sk-…`,keyDraft:s,onKeyDraftChange:c,onSaveKey:x,onClearKey:C,probe:t}),(y||_===`cloud`)&&(0,h.jsxs)(`fieldset`,{className:`provider-row`,style:{flexDirection:`column`,alignItems:`flex-start`},children:[(0,h.jsx)(`legend`,{children:`Cost confirmation`}),(0,h.jsx)(`p`,{className:`muted small`,children:`Cloud image generations cost real money. Choose whether you want to be asked before each cloud generation.`}),(0,h.jsxs)(`label`,{className:`provider-row`,children:[(0,h.jsx)(`input`,{type:`radio`,name:`image-confirmation`,value:`ask`,checked:k===`ask`,onChange:()=>void O(`ask`)}),(0,h.jsx)(`span`,{children:`Ask before each cloud image (default)`})]}),(0,h.jsxs)(`label`,{className:`provider-row`,children:[(0,h.jsx)(`input`,{type:`radio`,name:`image-confirmation`,value:`always-allow`,checked:k===`always-allow`,onChange:()=>void O(`always-allow`)}),(0,h.jsx)(`span`,{children:`Always allow without asking`})]})]}),l&&(0,h.jsx)(`p`,{className:`muted small`,children:l})]})}function T({providerLabel:e,modelId:t,docsHref:n,hasKey:r,maskedKey:i,keyPlaceholder:a,keyDraft:o,onKeyDraftChange:s,onSaveKey:c,onClearKey:l,probe:u}){return(0,h.jsxs)(h.Fragment,{children:[(0,h.jsxs)(`p`,{className:`muted small`,children:[`Generate images through `,(0,h.jsx)(`strong`,{children:e}),`. Models are managed by the provider; you only need an API key. Default model: `,(0,h.jsx)(`code`,{children:t}),`.`,` `,(0,h.jsx)(`a`,{href:n,target:`_blank`,rel:`noreferrer`,children:`Provider docs ↗`})]}),u.kind===`engine-not-configured`&&(0,h.jsxs)(`p`,{className:`error`,children:[`API key not configured. Add a key below to enable `,e,`.`]}),u.kind===`engine-unreachable`&&(0,h.jsxs)(`p`,{className:`error`,children:[e,` isn't reachable.`,u.status.engine.error&&(0,h.jsxs)(h.Fragment,{children:[` `,(0,h.jsxs)(`span`,{className:`muted small`,children:[`Details: `,u.status.engine.error]})]})]}),(0,h.jsxs)(`div`,{className:`provider-row`,children:[(0,h.jsxs)(`span`,{children:[`API key `,r&&(0,h.jsxs)(`span`,{className:`muted small`,children:[`(`,i,`)`]})]}),(0,h.jsx)(`input`,{type:`password`,autoComplete:`off`,placeholder:a,value:o,onChange:e=>s(e.target.value),style:{flex:1}}),(0,h.jsx)(`button`,{type:`button`,onClick:c,disabled:!o.trim(),children:`Save`}),r&&(0,h.jsx)(`button`,{type:`button`,className:`subtle`,onClick:l,children:`Clear`})]})]})}function E(e){return e===`always-allow`?`always-allow`:`ask`}function D({probe:e}){switch(e.kind){case`idle`:case`probing`:return(0,h.jsx)(`span`,{className:`gz-status-pill`,children:`Probing…`});case`ready`:return(0,h.jsx)(`span`,{className:`gz-status-pill gz-status-pill--ok`,children:`Ready`});case`no-models`:return(0,h.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,children:`No local models`});case`engine-not-configured`:return(0,h.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,children:`Engine not configured`});case`engine-unreachable`:return(0,h.jsx)(`span`,{className:`gz-status-pill gz-status-pill--fail`,children:`Engine unreachable`});case`probe-failed`:return(0,h.jsx)(`span`,{className:`gz-status-pill gz-status-pill--fail`,children:`Service unreachable`})}}export{w as ImageEngineSettings};
1
+ import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{n as t,t as n}from"./jsx-runtime-CEpd2cAX.js";import{It as r}from"./dist-BqGwkOe5.js";import{t as i}from"./api-BPraLwsh.js";import{G as a,J as o,K as s,W as c,Y as l,q as u}from"./primitives-CWrGZpPI.js";import{t as d}from"./ConfirmDialog-Dt1ed4Fh.js";import{t as f}from"./CatalogBrowser-DEM9t7Es.js";import{t as p}from"./LicenseButton-D3VmcVG1.js";var m=e(t(),1),h=n(),g=`image-generator`,_=`generate_image`;function v(){let[e,t]=(0,m.useState)([]),[n,r]=(0,m.useState)(!0),[a,o]=(0,m.useState)(!1),s=(0,m.useCallback)(async()=>{r(!0);try{let e=await i.listGezels();t(e.gezels)}catch{}finally{r(!1)}},[]);(0,m.useEffect)(()=>{s();let e=()=>void s();return window.addEventListener(`gezel:gezel-updated`,e),()=>window.removeEventListener(`gezel:gezel-updated`,e)},[s]);let c=(0,m.useMemo)(()=>e.filter(e=>e.fixedFunction?.tool===_),[e]),l=(0,m.useCallback)(e=>{window.dispatchEvent(new CustomEvent(`gezel:open-tab`,{detail:{kind:`gezel`,id:e,activate:!0}}))},[]),u=(0,m.useCallback)(e=>{o(!1),s(),l(e.id)},[s,l]);return n?null:(0,h.jsxs)(`div`,{className:`ff-img-hint`,children:[c.length>0?(0,h.jsxs)(`div`,{className:`ff-img-hint-have`,children:[(0,h.jsx)(`span`,{className:`muted small`,children:`Image-generator gezel`}),c.length===1?(0,h.jsx)(`button`,{type:`button`,className:`link-btn`,onClick:()=>l(c[0].id),title:`Open ${c[0].name}`,children:c[0].name}):(0,h.jsx)(`span`,{children:c.map((e,t)=>(0,h.jsxs)(`span`,{children:[(0,h.jsx)(`button`,{type:`button`,className:`link-btn`,onClick:()=>l(e.id),title:`Open ${e.name}`,children:e.name}),t<c.length-1&&(0,h.jsx)(`span`,{className:`muted`,children:`, `})]},e.id))}),(0,h.jsx)(`span`,{className:`muted small`,children:`— @-mention them in chat to generate.`})]}):(0,h.jsxs)(`div`,{className:`ff-img-hint-empty`,children:[(0,h.jsxs)(`p`,{className:`muted small`,children:[`Once an engine is set up, the easiest way to use it from chat is to add an`,` `,(0,h.jsx)(`strong`,{children:`image-generator gezel`}),`. They forward your @-mention text straight to`,` `,(0,h.jsx)(`code`,{children:_}),` — no LLM in the middle.`]}),(0,h.jsx)(`button`,{type:`button`,className:`primary`,onClick:()=>o(!0),children:`Add an image-generator gezel`})]}),(0,h.jsx)(y,{open:a,onClose:()=>o(!1),onCreated:u})]})}function y({open:e,onClose:t,onCreated:n}){let[d,f]=(0,m.useState)(()=>r()),[p,v]=(0,m.useState)(null),[y,b]=(0,m.useState)(!1),[x,S]=(0,m.useState)(null),[C,w]=(0,m.useState)(!1),T=(0,m.useRef)(!1);(0,m.useEffect)(()=>{!e||T.current||(T.current=!0,w(!0),i.getCatalogItem(`gezel-template`,g).then(e=>{e.manifest.kind===`gezel-template`&&v(e.manifest.description)}).catch(e=>{S(e instanceof Error?e.message:String(e))}).finally(()=>w(!1)))},[e]),(0,m.useEffect)(()=>{e&&(f(r()),S(null),b(!1))},[e]);let E=()=>f(r()),D=(0,m.useCallback)(async()=>{if(d.trim()){b(!0),S(null);try{n(await i.createGezelFromTemplate(g,{name:d.trim()}))}catch(e){S(e instanceof Error?e.message:String(e))}finally{b(!1)}}},[d,n]);return(0,h.jsx)(o,{open:e,onOpenChange:e=>{!e&&!y&&t()},children:(0,h.jsxs)(u,{children:[(0,h.jsx)(s,{}),(0,h.jsxs)(c,{className:`template-picker-dialog`,children:[(0,h.jsxs)(`header`,{style:{display:`flex`,justifyContent:`space-between`,alignItems:`baseline`},children:[(0,h.jsx)(l,{asChild:!0,children:(0,h.jsx)(`h3`,{style:{margin:0},children:`Add an image-generator gezel`})}),(0,h.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:t,disabled:y,children:`Cancel`})]}),(0,h.jsxs)(a,{className:`muted small`,style:{margin:`0.25rem 0 0.5rem 0`},children:[`Forwards your @-mention text straight to `,(0,h.jsx)(`code`,{children:_}),`. No LLM is invoked.`]}),C&&(0,h.jsx)(`p`,{className:`muted small`,children:`Loading template…`}),p&&(0,h.jsx)(`p`,{className:`muted small`,children:p}),(0,h.jsx)(`form`,{onSubmit:e=>{e.preventDefault(),D()},style:{marginTop:`0.5rem`,padding:`0.6rem`,background:`rgba(79, 125, 255, 0.06)`,borderRadius:`6px`,display:`flex`,flexDirection:`column`,gap:`0.5rem`},children:(0,h.jsxs)(`div`,{style:{display:`flex`,gap:`0.5rem`,alignItems:`center`},children:[(0,h.jsx)(`span`,{className:`muted small`,style:{flexShrink:0},children:`Name:`}),(0,h.jsx)(`input`,{value:d,onChange:e=>f(e.target.value),disabled:y,style:{flex:1}}),(0,h.jsx)(`button`,{type:`button`,className:`dice-btn`,onClick:E,disabled:y,title:`Pick a random name`,"aria-label":`Pick a random name`,children:`🎲`}),(0,h.jsx)(`button`,{type:`submit`,className:`primary`,disabled:y||!d.trim(),children:y?`Creating…`:`Create`})]})}),x&&(0,h.jsx)(`p`,{className:`error`,children:x})]})]})})}function b(e){return e>=1024**3?`${(e/1024**3).toFixed(1)} GB`:e>=1024**2?`${(e/1024**2).toFixed(0)} MB`:e>=1024?`${(e/1024).toFixed(0)} KB`:`${e} B`}function x(e,t){switch(e){case`low`:return`Runs on ${t} GB`;case`mid`:return`${t} GB+`;case`high`:return`${t} GB+ recommended`;case`workstation`:return`${t} GB+ workstation`}}function S({disabledReason:e,onModelsChanged:t,configuredDefaultModelId:n,onSetActiveModel:r}){let[a,o]=(0,m.useState)([]),[s,c]=(0,m.useState)(null),[l,u]=(0,m.useState)(new Map),[g,_]=(0,m.useState)(null),v=(0,m.useRef)(l);v.current=l;let y=(0,m.useCallback)(async()=>{try{let e=await i.listInstalledImageModels();o(e.models),c(null)}catch(e){o([]),c(e.message)}},[]),S=(0,m.useCallback)((e,n)=>{let r=new AbortController;u(t=>{let n=new Map(t),i=n.get(e);return n.set(e,{...i??{id:e,bytesWritten:0,totalBytes:0},controller:r}),n}),n(n=>{n.type===`progress`?u(t=>{let r=new Map(t),i=r.get(e);if(!i)return t;let{retrying:a,...o}=i;return r.set(e,{...o,bytesWritten:n.bytesWritten,totalBytes:n.totalBytes??i.totalBytes}),r}):n.type===`retrying`?u(t=>{let r=new Map(t),i=r.get(e);return i?(r.set(e,{...i,retrying:{attempt:n.attempt,maxAttempts:n.maxAttempts,delayMs:n.delayMs,reason:n.reason}}),r):t}):n.type===`error`?u(t=>{let r=new Map(t),i=r.get(e);return i&&r.set(e,{...i,error:n.error,retrying:void 0}),r}):n.type===`done`&&setTimeout(()=>{u(t=>{let n=new Map(t);return n.delete(e),n}),y(),t?.()},800)},r.signal).catch(t=>{r.signal.aborted||u(n=>{let r=new Map(n),i=r.get(e);return i&&r.set(e,{...i,error:t.message}),r})})},[y,t]);(0,m.useEffect)(()=>{y();let e=!1;return i.listActiveImagePulls().then(({pulls:t})=>{if(!e)for(let e of t)e.finished||(u(t=>{if(t.has(e.id))return t;let n=new Map(t);return n.set(e.id,{id:e.id,bytesWritten:e.bytesWritten,totalBytes:e.totalBytes,controller:new AbortController,...e.retrying?{retrying:e.retrying}:{},...e.error?{error:e.error}:{}}),n}),S(e.id,(t,n)=>i.subscribeImagePull(e.id,t,n)))}).catch(()=>{}),()=>{e=!0}},[y,S]);let w=(0,m.useCallback)(e=>{v.current.has(e)||S(e,(t,n)=>i.pullImageModel(e,t,n))},[S]),T=(0,m.useCallback)(e=>{v.current.get(e)?.controller.abort(),u(t=>{let n=new Map(t);return n.delete(e),n}),S(e,(t,n)=>i.pullImageModel(e,t,n))},[S]),E=(0,m.useCallback)(e=>{v.current.get(e)?.controller.abort(),u(t=>{let n=new Map(t);return n.delete(e),n}),i.cancelImagePull(e).catch(()=>{})},[]),D=(0,m.useCallback)(async()=>{if(g)try{await i.deleteImageModel(g),await y(),t?.()}catch(e){c(e.message)}finally{_(null)}},[g,y,t]),O=(0,m.useMemo)(()=>new Set(a.map(e=>e.id)),[a]),k=!!r&&a.length>0,A=n&&O.has(n)?n:a[0]?.id;return(0,h.jsxs)(`div`,{className:`ollama-model-manager`,children:[l.size>0&&(0,h.jsxs)(`div`,{className:`ollama-section`,children:[(0,h.jsx)(`h4`,{children:`Downloading…`}),(0,h.jsx)(`div`,{className:`ollama-pull-list`,children:Array.from(l.values()).map(e=>(0,h.jsx)(C,{pull:e,onCancel:()=>E(e.id),onRetry:()=>T(e.id)},e.id))})]}),(a.length>0||s)&&(0,h.jsxs)(`div`,{className:`ollama-section`,children:[(0,h.jsx)(`h4`,{children:`Local models`}),s&&(0,h.jsx)(`p`,{className:`error`,children:s}),k&&a.length>1&&(0,h.jsxs)(`p`,{className:`muted small`,children:[`The `,(0,h.jsx)(`strong`,{children:`active`}),` model is what the image-generator gezel and the`,` `,(0,h.jsx)(`code`,{children:`render_image`}),` tool use by default. A gezel can still ask for a specific model per image; switching reloads the engine, which takes a moment.`]}),a.length>0&&(0,h.jsxs)(`table`,{className:`ollama-model-table`,children:[(0,h.jsx)(`thead`,{children:(0,h.jsxs)(`tr`,{children:[k&&(0,h.jsx)(`th`,{scope:`col`,className:`gz-active-model-column`,children:`Active`}),(0,h.jsx)(`th`,{children:`Name`}),(0,h.jsx)(`th`,{children:`Size`}),(0,h.jsx)(`th`,{children:`Added`}),(0,h.jsx)(`th`,{})]})}),(0,h.jsx)(`tbody`,{children:a.map(e=>(0,h.jsxs)(`tr`,{children:[k&&(0,h.jsx)(`td`,{className:`gz-active-model-column`,children:(0,h.jsx)(`input`,{type:`radio`,name:`active-image-model`,className:`gz-active-model-radio`,"aria-label":`Use ${e.id} as the active image model`,checked:A===e.id,onChange:()=>{A!==e.id&&r?.(e.id)}})}),(0,h.jsxs)(`td`,{children:[(0,h.jsx)(`code`,{children:e.id}),(0,h.jsx)(`div`,{className:`muted small`,children:e.name})]}),(0,h.jsx)(`td`,{children:b(e.approxSizeBytes)}),(0,h.jsx)(`td`,{className:`muted small`,children:new Date(e.installedAt).toLocaleDateString()}),(0,h.jsx)(`td`,{children:(0,h.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:()=>_(e.id),children:`Delete`})})]},e.id))})]})]}),(0,h.jsxs)(`div`,{className:`ollama-section ollama-section--flat ollama-section--download`,children:[(0,h.jsx)(`h4`,{children:`Download a model`}),(0,h.jsx)(f,{kind:`image-model`,emptyMessage:`No image models in the catalog yet. Remote catalog sources can add entries without an app update.`,action:t=>{if(t.manifest.kind!==`image-model`)return null;let n=t.manifest,r=O.has(n.id),i=l.get(n.id),a=!!i,o=i&&i.totalBytes>0?Math.min(100,Math.round(i.bytesWritten/i.totalBytes*100)):null;return(0,h.jsxs)(`div`,{className:`catalog-ollama-action`,children:[(0,h.jsxs)(`div`,{className:`catalog-ollama-meta`,children:[(0,h.jsxs)(`div`,{className:`catalog-ollama-specs muted small`,children:[(0,h.jsx)(`code`,{children:n.id}),(0,h.jsx)(`span`,{children:`·`}),(0,h.jsx)(`span`,{children:b(n.approxSizeBytes)}),n.quantization&&(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{children:`·`}),(0,h.jsx)(`span`,{children:n.quantization})]}),(0,h.jsx)(`span`,{children:`·`}),(0,h.jsx)(`span`,{children:x(n.hardwareTier,n.minRamGB)})]}),(0,h.jsx)(`div`,{className:`catalog-ollama-pills`,children:(0,h.jsx)(p,{manifest:n})})]}),(0,h.jsx)(`button`,{type:`button`,disabled:r||a||!!e,title:e??void 0,onClick:()=>void w(n.id),children:r?`On device`:a?o===null?`Downloading…`:`Downloading… ${o}%`:`Download`})]})}})]}),(0,h.jsx)(d,{open:g!==null,title:`Delete image model?`,message:g?`"${g}" will be removed from local storage. This frees disk space; download it again later to use it.`:``,confirmLabel:`Delete`,danger:!0,onCancel:()=>_(null),onConfirm:D})]})}function C({pull:e,onCancel:t,onRetry:n}){let r=e.totalBytes>0,i=r?Math.min(100,Math.round(e.bytesWritten/e.totalBytes*100)):0,a;if(e.error)a=e.error;else if(e.retrying){let t=Math.max(1,Math.round(e.retrying.delayMs/1e3));a=`${e.retrying.reason} — retrying in ${t}s (attempt ${e.retrying.attempt}/${e.retrying.maxAttempts})`}else a=r?`Downloading… (${b(e.bytesWritten)} of ${b(e.totalBytes)}, ${i}%)`:e.bytesWritten>0?`Downloading… (${b(e.bytesWritten)})`:`Preparing download…`;return(0,h.jsxs)(`div`,{className:`ollama-pull${e.error?` ollama-pull-error`:e.retrying?` ollama-pull-warning`:``}`,children:[(0,h.jsxs)(`div`,{className:`ollama-pull-head`,children:[(0,h.jsx)(`code`,{children:e.id}),(0,h.jsx)(`span`,{className:`muted small`,children:a}),e.error?(0,h.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:n,children:`Retry`}):(0,h.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:t,children:`Cancel`})]}),r?(0,h.jsxs)(`div`,{className:`ollama-pull-bar`,children:[(0,h.jsx)(`div`,{className:`ollama-pull-bar-fill`,style:{width:`${i}%`}}),(0,h.jsxs)(`span`,{className:`ollama-pull-bar-label`,children:[i,`%`]})]}):(0,h.jsx)(`div`,{className:`ollama-pull-bar ollama-pull-bar-indeterminate`,children:(0,h.jsx)(`div`,{className:`ollama-pull-bar-fill`})})]})}function w({onModelsChanged:e}){let[t,n]=(0,m.useState)({kind:`idle`}),[r,a]=(0,m.useState)(0),[o,s]=(0,m.useState)(null),[c,l]=(0,m.useState)(``),[u,d]=(0,m.useState)(null),f=(0,m.useCallback)(async()=>{n({kind:`probing`});try{let[e,t]=await Promise.all([i.getImageEngineStatus(),i.getConfig()]);s(t),e.engine.status===`not-configured`?n({kind:`engine-not-configured`,status:e}):e.engine.status===`unreachable`?n({kind:`engine-unreachable`,status:e}):e.modelCount===0?n({kind:`no-models`,status:e}):n({kind:`ready`,status:e})}catch(e){n({kind:`probe-failed`,error:e.message})}},[]);(0,m.useEffect)(()=>{f()},[f,r]);let p=t.kind===`engine-not-configured`||t.kind===`engine-unreachable`||t.kind===`probe-failed`,g=o?.imageProvider??`sd-cpp`,_=`status`in t?t.status.engine.kind??`local`:`local`,y=g===`google-ai`||g===`openai`,b=(0,m.useCallback)(async e=>{d(`switching engine…`);try{let t=await i.updateConfig({imageProvider:e});s(t),l(``),d(null),a(e=>e+1)}catch(e){d(`switch failed: ${e.message}`)}},[]),x=(0,m.useCallback)(async()=>{if(c.trim()){d(`saving key…`);try{let e=g===`google-ai`?{googleAiApiKey:c.trim()}:g===`openai`?{openaiApiKey:c.trim()}:{},t=await i.updateConfig(e);s(t),l(``),d(`key saved`),a(e=>e+1)}catch(e){d(`save failed: ${e.message}`)}}},[c,g]),C=(0,m.useCallback)(async()=>{d(`clearing key…`);try{let e=g===`google-ai`?{googleAiApiKey:``}:g===`openai`?{openaiApiKey:``}:{},t=await i.updateConfig(e);s(t),l(``),d(`key cleared`),a(e=>e+1)}catch(e){d(`clear failed: ${e.message}`)}},[g]),w=(0,m.useCallback)(async e=>{d(`saving…`);try{let t=await i.updateConfig({defaultImageModel:{...o?.defaultImageModel,"sd-cpp":e}});s(t),d(null)}catch(e){d(`save failed: ${e.message}`)}},[o?.defaultImageModel]),O=(0,m.useCallback)(async e=>{d(`saving…`);try{let t=await i.updateConfig({imageGenerationConfirmation:e});s(t),d(null)}catch(e){d(`save failed: ${e.message}`)}},[]),k=E(o?.imageGenerationConfirmation);return(0,h.jsxs)(`div`,{className:`provider-card`,children:[(0,h.jsxs)(`div`,{className:`settings-card-header`,children:[(0,h.jsx)(`h3`,{children:`Image generation`}),(0,h.jsx)(D,{probe:t})]}),(0,h.jsx)(v,{}),(0,h.jsxs)(`label`,{className:`provider-row`,children:[(0,h.jsx)(`span`,{children:`Engine`}),(0,h.jsxs)(`select`,{value:g,onChange:e=>void b(e.target.value),children:[(0,h.jsx)(`option`,{value:`sd-cpp`,children:`Local (Stable Diffusion)`}),(0,h.jsx)(`option`,{value:`google-ai`,children:`Google Nano Banana 2 (cloud)`}),(0,h.jsx)(`option`,{value:`openai`,children:`OpenAI GPT Image 2 (cloud)`})]})]}),g===`sd-cpp`&&(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`p`,{className:`muted small`,children:`Generate images locally through the bundled Stable Diffusion engine.`}),t.kind===`engine-not-configured`&&(0,h.jsxs)(`p`,{className:`error`,children:[`The image engine isn't wired up on this install. Models on disk can't run on their own — they need the `,(0,h.jsx)(`code`,{children:`sd-server`}),` binary or an external server. Set`,` `,(0,h.jsx)(`code`,{children:`GEZEL_SD_SERVER_URL`}),` to point at a running sd-server, or build the bundled binary at`,` `,(0,h.jsxs)(`code`,{children:[`native/build/`,`<`,`platform`,`>`,`/sd-server`]}),`.`,t.status.engine.error&&(0,h.jsxs)(h.Fragment,{children:[` `,(0,h.jsxs)(`span`,{className:`muted small`,children:[`Details: `,t.status.engine.error]})]})]}),t.kind===`engine-unreachable`&&(0,h.jsxs)(`p`,{className:`error`,children:[`The image engine is configured but isn't responding at`,` `,(0,h.jsx)(`code`,{children:t.status.engine.baseUrl}),`. Check whether `,(0,h.jsx)(`code`,{children:`sd-server`}),` is running.`,t.status.engine.error&&(0,h.jsxs)(h.Fragment,{children:[` `,(0,h.jsxs)(`span`,{className:`muted small`,children:[`Details: `,t.status.engine.error]})]})]}),t.kind===`probe-failed`&&(0,h.jsxs)(`p`,{className:`error`,children:[`Couldn't reach the Gezel service. Details: `,t.error]}),(0,h.jsx)(S,{...p?{disabledReason:t.kind===`engine-not-configured`?`Image engine is not configured — downloading a model now would still leave it unrunnable.`:`Image engine is not reachable.`}:{},...o?.defaultImageModel?.[`sd-cpp`]?{configuredDefaultModelId:o.defaultImageModel[`sd-cpp`]}:{},onSetActiveModel:w,onModelsChanged:()=>{a(e=>e+1),e?.()}})]}),g===`google-ai`&&(0,h.jsx)(T,{providerLabel:`Google Nano Banana 2`,modelId:`gemini-3.1-flash-image-preview`,docsHref:`https://ai.google.dev/gemini-api/docs/image-generation`,hasKey:o?.hasGoogleAiApiKey===!0,maskedKey:o?.googleAiApiKey,keyPlaceholder:`AIza…`,keyDraft:c,onKeyDraftChange:l,onSaveKey:x,onClearKey:C,probe:t}),g===`openai`&&(0,h.jsx)(T,{providerLabel:`OpenAI GPT Image 2`,modelId:`gpt-image-2`,docsHref:`https://developers.openai.com/api/docs/models/gpt-image-2`,hasKey:o?.hasOpenaiApiKey===!0,maskedKey:o?.openaiApiKey,keyPlaceholder:`sk-…`,keyDraft:c,onKeyDraftChange:l,onSaveKey:x,onClearKey:C,probe:t}),(y||_===`cloud`)&&(0,h.jsxs)(`fieldset`,{className:`provider-row`,style:{flexDirection:`column`,alignItems:`flex-start`},children:[(0,h.jsx)(`legend`,{children:`Cost confirmation`}),(0,h.jsx)(`p`,{className:`muted small`,children:`Cloud image generations cost real money. Choose whether you want to be asked before each cloud generation.`}),(0,h.jsxs)(`label`,{className:`provider-row`,children:[(0,h.jsx)(`input`,{type:`radio`,name:`image-confirmation`,value:`ask`,checked:k===`ask`,onChange:()=>void O(`ask`)}),(0,h.jsx)(`span`,{children:`Ask before each cloud image (default)`})]}),(0,h.jsxs)(`label`,{className:`provider-row`,children:[(0,h.jsx)(`input`,{type:`radio`,name:`image-confirmation`,value:`always-allow`,checked:k===`always-allow`,onChange:()=>void O(`always-allow`)}),(0,h.jsx)(`span`,{children:`Always allow without asking`})]})]}),u&&(0,h.jsx)(`p`,{className:`muted small`,children:u})]})}function T({providerLabel:e,modelId:t,docsHref:n,hasKey:r,maskedKey:i,keyPlaceholder:a,keyDraft:o,onKeyDraftChange:s,onSaveKey:c,onClearKey:l,probe:u}){return(0,h.jsxs)(h.Fragment,{children:[(0,h.jsxs)(`p`,{className:`muted small`,children:[`Generate images through `,(0,h.jsx)(`strong`,{children:e}),`. Models are managed by the provider; you only need an API key. Default model: `,(0,h.jsx)(`code`,{children:t}),`.`,` `,(0,h.jsx)(`a`,{href:n,target:`_blank`,rel:`noreferrer`,children:`Provider docs ↗`})]}),u.kind===`engine-not-configured`&&(0,h.jsxs)(`p`,{className:`error`,children:[`API key not configured. Add a key below to enable `,e,`.`]}),u.kind===`engine-unreachable`&&(0,h.jsxs)(`p`,{className:`error`,children:[e,` isn't reachable.`,u.status.engine.error&&(0,h.jsxs)(h.Fragment,{children:[` `,(0,h.jsxs)(`span`,{className:`muted small`,children:[`Details: `,u.status.engine.error]})]})]}),(0,h.jsxs)(`div`,{className:`provider-row`,children:[(0,h.jsxs)(`span`,{children:[`API key `,r&&(0,h.jsxs)(`span`,{className:`muted small`,children:[`(`,i,`)`]})]}),(0,h.jsx)(`input`,{type:`password`,autoComplete:`off`,placeholder:a,value:o,onChange:e=>s(e.target.value),style:{flex:1}}),(0,h.jsx)(`button`,{type:`button`,onClick:c,disabled:!o.trim(),children:`Save`}),r&&(0,h.jsx)(`button`,{type:`button`,className:`subtle`,onClick:l,children:`Clear`})]})]})}function E(e){return e===`always-allow`?`always-allow`:`ask`}function D({probe:e}){switch(e.kind){case`idle`:case`probing`:return(0,h.jsx)(`span`,{className:`gz-status-pill`,children:`Probing…`});case`ready`:return(0,h.jsx)(`span`,{className:`gz-status-pill gz-status-pill--ok`,children:`Ready`});case`no-models`:return(0,h.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,children:`No local models`});case`engine-not-configured`:return(0,h.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,children:`Engine not configured`});case`engine-unreachable`:return(0,h.jsx)(`span`,{className:`gz-status-pill gz-status-pill--fail`,children:`Engine unreachable`});case`probe-failed`:return(0,h.jsx)(`span`,{className:`gz-status-pill gz-status-pill--fail`,children:`Service unreachable`})}}export{w as ImageEngineSettings};
@@ -1 +1 @@
1
- import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{n as t,t as n}from"./jsx-runtime-CEpd2cAX.js";import{t as r}from"./api-BX5xXiFs.js";import{t as i}from"./ConfirmDialog-BHFs6vmJ.js";var a=e(t(),1),o=n();function s(e){return e>=1024**3?`${(e/1024**3).toFixed(1)} GB`:e>=1024**2?`${(e/1024**2).toFixed(0)} MB`:e>=1024?`${(e/1024).toFixed(0)} KB`:`${e} B`}var c=[{value:`auto`,label:`When needed`,hint:`Only when the model can't see`},{value:`always`,label:`Always`,hint:`Even for models that can`},{value:`off`,label:`Never`,hint:`Metadata only`}];function l(){let[e,t]=(0,a.useState)(null),[n,l]=(0,a.useState)([]),[f,p]=(0,a.useState)([]),[m,h]=(0,a.useState)(null),[g,_]=(0,a.useState)(`auto`),[v,y]=(0,a.useState)(!1),[b,x]=(0,a.useState)(new Map),[S,C]=(0,a.useState)(null),[w,T]=(0,a.useState)(!1),E=(0,a.useRef)(b);E.current=b;let D=(0,a.useCallback)(async()=>{try{let[e,n,i,a]=await Promise.all([r.getRecognitionHealth(),r.listInstalledRecognitionModels(),r.listRecognitionCatalog(),r.getConfig()]);t(e),l(n.models),p(i.models),_(a.recognition?.mode??`auto`),h(null)}catch(e){h(e.message)}},[]);(0,a.useEffect)(()=>{D()},[D]);let O=(0,a.useCallback)(async e=>{let t=g;_(e),y(!0);try{let t=await r.updateConfig({recognition:{mode:e}});window.dispatchEvent(new CustomEvent(`gezel:config-updated`,{detail:t}))}catch(e){_(t),h(e.message)}finally{y(!1)}},[g]),k=(0,a.useCallback)(e=>{let t=new AbortController;x(n=>new Map(n).set(e.id,{id:e.id,bytesWritten:0,totalBytes:e.approxSizeBytes,controller:t})),r.pullRecognitionModel(e.id,t=>{x(n=>{let r=new Map(n),i=r.get(e.id);return i?(t.type===`progress`?r.set(e.id,{...i,bytesWritten:t.bytesWritten,totalBytes:t.totalBytes??i.totalBytes}):t.type===`error`?r.set(e.id,{...i,error:t.error}):r.delete(e.id),r):n}),t.type===`done`&&D()},t.signal).catch(t=>{x(n=>{let r=new Map(n),i=r.get(e.id);return i&&r.set(e.id,{...i,error:t.message}),r})})},[D]),A=(0,a.useCallback)(async e=>{C(null);try{await r.deleteRecognitionModel(e),await D()}catch(e){h(e.message)}},[D]),j=(0,a.useCallback)(async()=>{try{await r.clearRecognitionCache(),T(!0),window.setTimeout(()=>T(!1),2500)}catch(e){h(e.message)}},[]),M=new Set(n.map(e=>e.id));return(0,o.jsxs)(`div`,{className:`provider-card`,children:[(0,o.jsxs)(`div`,{className:`settings-card-header`,children:[(0,o.jsx)(`h3`,{children:`Image recognition`}),e&&(0,o.jsx)(u,{health:e})]}),(0,o.jsxs)(`p`,{className:`muted small`,children:[`Most models can't see images. When someone pastes a screenshot into a chat with a model that has no vision, a small local model reads the image and passes along a description — so the conversation still works. Runs entirely on this device; weights live under`,` `,(0,o.jsx)(`code`,{children:`~/.gezel/engines/recognition/`}),`. Also available to any gezel through the`,` `,(0,o.jsx)(`code`,{children:`describe_image`}),` tool.`]}),m&&(0,o.jsx)(`p`,{className:`error`,children:m}),(0,o.jsx)(d,{health:e}),(0,o.jsxs)(`section`,{style:{marginTop:`1rem`},children:[(0,o.jsx)(`h4`,{style:{margin:`0 0 0.35rem`},children:`When to read images locally`}),(0,o.jsx)(`p`,{className:`muted small`,style:{marginTop:0},children:`"Always" keeps images on this device even when the chat model could see them itself — cheaper than sending pictures to a paid model, and nothing leaves the machine. Individual gezels can override this.`}),(0,o.jsx)(`div`,{className:`gz-tray`,role:`radiogroup`,"aria-label":`When to read images locally`,children:c.map(e=>(0,o.jsxs)(`button`,{type:`button`,role:`radio`,"aria-checked":g===e.value,disabled:v,className:`gz-key gz-key--stacked${g===e.value?` gz-key-active`:``}`,onClick:()=>void O(e.value),children:[(0,o.jsx)(`span`,{children:e.label}),(0,o.jsx)(`small`,{children:e.hint})]},e.value))})]}),(0,o.jsxs)(`section`,{className:`ollama-section`,style:{marginTop:`1.5rem`},children:[(0,o.jsx)(`h4`,{children:`Models`}),(0,o.jsx)(`div`,{className:`catalog-ollama-list`,children:f.map(e=>{let t=M.has(e.id),n=b.get(e.id),r=n&&n.totalBytes>0?Math.min(100,Math.round(n.bytesWritten/n.totalBytes*100)):null;return(0,o.jsxs)(`div`,{className:`catalog-ollama-action`,children:[(0,o.jsxs)(`div`,{className:`catalog-ollama-meta`,children:[(0,o.jsxs)(`div`,{className:`catalog-ollama-specs muted small`,children:[(0,o.jsx)(`code`,{children:e.id}),(0,o.jsx)(`span`,{children:`·`}),(0,o.jsx)(`span`,{children:s(e.approxSizeBytes)}),(0,o.jsx)(`span`,{children:`·`}),(0,o.jsx)(`span`,{children:e.license})]}),(0,o.jsxs)(`div`,{className:`muted small`,children:[(0,o.jsx)(`strong`,{children:e.name}),` — `,e.description]}),n?.error&&(0,o.jsx)(`div`,{className:`error small`,children:n.error})]}),n?(0,o.jsx)(`button`,{type:`button`,onClick:()=>{n.controller.abort(),x(t=>{let n=new Map(t);return n.delete(e.id),n})},children:r===null?`Downloading…`:`Downloading… ${r}%`}):t?(0,o.jsx)(`button`,{type:`button`,onClick:()=>C(e.id),children:`Remove`}):(0,o.jsx)(`button`,{type:`button`,onClick:()=>k(e),children:`Download`})]},e.id)})})]}),(0,o.jsxs)(`section`,{className:`ollama-section`,style:{marginTop:`1.25rem`},children:[(0,o.jsx)(`h4`,{children:`Cached descriptions`}),(0,o.jsx)(`p`,{className:`muted small`,style:{marginTop:0},children:`Each image is read once and the result is reused, keyed by its contents. Clearing is safe — anything still needed is read again on demand.`}),(0,o.jsx)(`button`,{type:`button`,onClick:()=>void j(),children:w?`Cleared`:`Clear cache`})]}),(0,o.jsx)(i,{open:S!==null,title:`Remove this model?`,message:`The weights are deleted from this device. You can download them again later.`,confirmLabel:`Remove`,danger:!0,onConfirm:()=>{S&&A(S)},onCancel:()=>C(null)})]})}function u({health:e}){return e.state===`ok`?(0,o.jsx)(`span`,{className:`gz-status-pill gz-status-pill--ok`,children:`Ready`}):e.state===`no-model`?(0,o.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,children:`No model`}):e.state===`error`?(0,o.jsx)(`span`,{className:`gz-status-pill gz-status-pill--error`,children:`Error`}):(0,o.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,children:`Unavailable`})}function d({health:e}){return!e||e.state===`ok`?null:e.state===`no-model`?(0,o.jsx)(`p`,{className:`muted small`,children:`Download a model below to turn this on. Until then, images pasted into a chat with a model that can't see are described only by their file details — size, format, and any text stored inside the file.`}):(0,o.jsx)(`p`,{className:`muted small`,children:e.detail??`The recognition engine is unavailable.`})}export{l as ImageRecognitionSettings};
1
+ import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{n as t,t as n}from"./jsx-runtime-CEpd2cAX.js";import{t as r}from"./api-BPraLwsh.js";import{t as i}from"./ConfirmDialog-Dt1ed4Fh.js";var a=e(t(),1),o=n();function s(e){return e>=1024**3?`${(e/1024**3).toFixed(1)} GB`:e>=1024**2?`${(e/1024**2).toFixed(0)} MB`:e>=1024?`${(e/1024).toFixed(0)} KB`:`${e} B`}var c=[{value:`auto`,label:`When needed`,hint:`Only when the model can't see`},{value:`always`,label:`Always`,hint:`Even for models that can`},{value:`off`,label:`Never`,hint:`Metadata only`}];function l(){let[e,t]=(0,a.useState)(null),[n,l]=(0,a.useState)([]),[f,p]=(0,a.useState)([]),[m,h]=(0,a.useState)(null),[g,_]=(0,a.useState)(`auto`),[v,y]=(0,a.useState)(!1),[b,x]=(0,a.useState)(new Map),[S,C]=(0,a.useState)(null),[w,T]=(0,a.useState)(!1),E=(0,a.useRef)(b);E.current=b;let D=(0,a.useCallback)(async()=>{try{let[e,n,i,a]=await Promise.all([r.getRecognitionHealth(),r.listInstalledRecognitionModels(),r.listRecognitionCatalog(),r.getConfig()]);t(e),l(n.models),p(i.models),_(a.recognition?.mode??`auto`),h(null)}catch(e){h(e.message)}},[]);(0,a.useEffect)(()=>{D()},[D]);let O=(0,a.useCallback)(async e=>{let t=g;_(e),y(!0);try{let t=await r.updateConfig({recognition:{mode:e}});window.dispatchEvent(new CustomEvent(`gezel:config-updated`,{detail:t}))}catch(e){_(t),h(e.message)}finally{y(!1)}},[g]),k=(0,a.useCallback)(e=>{let t=new AbortController;x(n=>new Map(n).set(e.id,{id:e.id,bytesWritten:0,totalBytes:e.approxSizeBytes,controller:t})),r.pullRecognitionModel(e.id,t=>{x(n=>{let r=new Map(n),i=r.get(e.id);return i?(t.type===`progress`?r.set(e.id,{...i,bytesWritten:t.bytesWritten,totalBytes:t.totalBytes??i.totalBytes}):t.type===`error`?r.set(e.id,{...i,error:t.error}):r.delete(e.id),r):n}),t.type===`done`&&D()},t.signal).catch(t=>{x(n=>{let r=new Map(n),i=r.get(e.id);return i&&r.set(e.id,{...i,error:t.message}),r})})},[D]),A=(0,a.useCallback)(async e=>{C(null);try{await r.deleteRecognitionModel(e),await D()}catch(e){h(e.message)}},[D]),j=(0,a.useCallback)(async()=>{try{await r.clearRecognitionCache(),T(!0),window.setTimeout(()=>T(!1),2500)}catch(e){h(e.message)}},[]),M=new Set(n.map(e=>e.id));return(0,o.jsxs)(`div`,{className:`provider-card`,children:[(0,o.jsxs)(`div`,{className:`settings-card-header`,children:[(0,o.jsx)(`h3`,{children:`Image recognition`}),e&&(0,o.jsx)(u,{health:e})]}),(0,o.jsxs)(`p`,{className:`muted small`,children:[`Most models can't see images. When someone pastes a screenshot into a chat with a model that has no vision, a small local model reads the image and passes along a description — so the conversation still works. Runs entirely on this device; weights live under`,` `,(0,o.jsx)(`code`,{children:`~/.gezel/engines/recognition/`}),`. Also available to any gezel through the`,` `,(0,o.jsx)(`code`,{children:`describe_image`}),` tool.`]}),m&&(0,o.jsx)(`p`,{className:`error`,children:m}),(0,o.jsx)(d,{health:e}),(0,o.jsxs)(`section`,{style:{marginTop:`1rem`},children:[(0,o.jsx)(`h4`,{style:{margin:`0 0 0.35rem`},children:`When to read images locally`}),(0,o.jsx)(`p`,{className:`muted small`,style:{marginTop:0},children:`"Always" keeps images on this device even when the chat model could see them itself — cheaper than sending pictures to a paid model, and nothing leaves the machine. Individual gezels can override this.`}),(0,o.jsx)(`div`,{className:`gz-tray`,role:`radiogroup`,"aria-label":`When to read images locally`,children:c.map(e=>(0,o.jsxs)(`button`,{type:`button`,role:`radio`,"aria-checked":g===e.value,disabled:v,className:`gz-key gz-key--stacked${g===e.value?` gz-key-active`:``}`,onClick:()=>void O(e.value),children:[(0,o.jsx)(`span`,{children:e.label}),(0,o.jsx)(`small`,{children:e.hint})]},e.value))})]}),(0,o.jsxs)(`section`,{className:`ollama-section`,style:{marginTop:`1.5rem`},children:[(0,o.jsx)(`h4`,{children:`Models`}),(0,o.jsx)(`div`,{className:`catalog-ollama-list`,children:f.map(e=>{let t=M.has(e.id),n=b.get(e.id),r=n&&n.totalBytes>0?Math.min(100,Math.round(n.bytesWritten/n.totalBytes*100)):null;return(0,o.jsxs)(`div`,{className:`catalog-ollama-action`,children:[(0,o.jsxs)(`div`,{className:`catalog-ollama-meta`,children:[(0,o.jsxs)(`div`,{className:`catalog-ollama-specs muted small`,children:[(0,o.jsx)(`code`,{children:e.id}),(0,o.jsx)(`span`,{children:`·`}),(0,o.jsx)(`span`,{children:s(e.approxSizeBytes)}),(0,o.jsx)(`span`,{children:`·`}),(0,o.jsx)(`span`,{children:e.license})]}),(0,o.jsxs)(`div`,{className:`muted small`,children:[(0,o.jsx)(`strong`,{children:e.name}),` — `,e.description]}),n?.error&&(0,o.jsx)(`div`,{className:`error small`,children:n.error})]}),n?(0,o.jsx)(`button`,{type:`button`,onClick:()=>{n.controller.abort(),x(t=>{let n=new Map(t);return n.delete(e.id),n})},children:r===null?`Downloading…`:`Downloading… ${r}%`}):t?(0,o.jsx)(`button`,{type:`button`,onClick:()=>C(e.id),children:`Remove`}):(0,o.jsx)(`button`,{type:`button`,onClick:()=>k(e),children:`Download`})]},e.id)})})]}),(0,o.jsxs)(`section`,{className:`ollama-section`,style:{marginTop:`1.25rem`},children:[(0,o.jsx)(`h4`,{children:`Cached descriptions`}),(0,o.jsx)(`p`,{className:`muted small`,style:{marginTop:0},children:`Each image is read once and the result is reused, keyed by its contents. Clearing is safe — anything still needed is read again on demand.`}),(0,o.jsx)(`button`,{type:`button`,onClick:()=>void j(),children:w?`Cleared`:`Clear cache`})]}),(0,o.jsx)(i,{open:S!==null,title:`Remove this model?`,message:`The weights are deleted from this device. You can download them again later.`,confirmLabel:`Remove`,danger:!0,onConfirm:()=>{S&&A(S)},onCancel:()=>C(null)})]})}function u({health:e}){return e.state===`ok`?(0,o.jsx)(`span`,{className:`gz-status-pill gz-status-pill--ok`,children:`Ready`}):e.state===`no-model`?(0,o.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,children:`No model`}):e.state===`error`?(0,o.jsx)(`span`,{className:`gz-status-pill gz-status-pill--error`,children:`Error`}):(0,o.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,children:`Unavailable`})}function d({health:e}){return!e||e.state===`ok`?null:e.state===`no-model`?(0,o.jsx)(`p`,{className:`muted small`,children:`Download a model below to turn this on. Until then, images pasted into a chat with a model that can't see are described only by their file details — size, format, and any text stored inside the file.`}):(0,o.jsx)(`p`,{className:`muted small`,children:e.detail??`The recognition engine is unavailable.`})}export{l as ImageRecognitionSettings};
@@ -0,0 +1 @@
1
+ import{t as e}from"./jsx-runtime-CEpd2cAX.js";import{Ft as t}from"./index-C0DYtvfg.js";var n=e();function r({items:e,onResume:r,onDelete:i}){return e.length===0?null:(0,n.jsxs)(`div`,{className:`ollama-section`,children:[(0,n.jsx)(`h4`,{children:`Incomplete downloads`}),(0,n.jsx)(`p`,{className:`muted small`,style:{marginBottom:`0.5rem`},children:`These downloads were interrupted or never finished checking. They take up disk space but aren't usable yet.`}),(0,n.jsx)(`div`,{className:`ollama-pull-list`,children:e.map(e=>(0,n.jsx)(`div`,{className:`ollama-pull`,children:(0,n.jsxs)(`div`,{className:`ollama-pull-head`,children:[(0,n.jsx)(`code`,{children:e.name??e.id}),(0,n.jsxs)(`span`,{className:`muted small`,children:[t(e.bytes),e.resumable?``:` · no longer in the catalog`]}),(0,n.jsxs)(`span`,{style:{display:`inline-flex`,gap:`0.75rem`},children:[e.resumable&&(0,n.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:()=>r(e.id),children:`Resume`}),(0,n.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:()=>i(e.id),children:`Delete`})]})]})},e.id))})]})}export{r as t};
@@ -0,0 +1 @@
1
+ import{t as e}from"./jsx-runtime-CEpd2cAX.js";var t=e();function n(e,t=`model`){let n=e.split(`/`).map(encodeURIComponent).join(`/`);return`https://huggingface.co/${t===`dataset`?`datasets/`:``}${n}`}function r({repo:e,repoType:r=`model`}){return(0,t.jsx)(`a`,{className:`hf-repo-link`,href:n(e,r),target:`_blank`,rel:`noreferrer`,title:`View ${e} on Hugging Face`,children:(0,t.jsx)(`code`,{children:e})})}function i({title:e,status:n,percent:r,tone:i=`normal`,onCancel:a,onRetry:o}){let s=r===null?null:Math.max(0,Math.min(100,Math.round(r)));return(0,t.jsxs)(`div`,{className:`ollama-pull${i===`error`?` ollama-pull-error`:i===`warning`?` ollama-pull-warning`:``}`,children:[(0,t.jsxs)(`div`,{className:`ollama-pull-head`,children:[e,(0,t.jsx)(`span`,{className:`muted small`,children:n}),i===`error`&&o?(0,t.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:o,children:`Retry`}):(0,t.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:a,children:`Cancel`})]}),s===null?(0,t.jsx)(`div`,{className:`ollama-pull-bar ollama-pull-bar-indeterminate`,children:(0,t.jsx)(`div`,{className:`ollama-pull-bar-fill`})}):(0,t.jsxs)(`div`,{className:`ollama-pull-bar`,children:[(0,t.jsx)(`div`,{className:`ollama-pull-bar-fill`,style:{width:`${s}%`}}),(0,t.jsxs)(`span`,{className:`ollama-pull-bar-label`,children:[s,`%`]})]})]})}export{r as n,n as r,i as t};
@@ -0,0 +1 @@
1
+ import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{n as t,t as n}from"./jsx-runtime-CEpd2cAX.js";import{t as r}from"./dist-BaHut5iX.js";import{t as i}from"./api-BPraLwsh.js";import{t as a}from"./ConfirmDialog-Dt1ed4Fh.js";import{i as o,n as s,t as c}from"./model-inventory-ykSm_IT5.js";import{Ft as l}from"./index-C0DYtvfg.js";import{t as u}from"./CatalogBrowser-DEM9t7Es.js";import{n as ee,r as d,t as f}from"./InstallProgressRow-DyKOI4MU.js";import{t as te}from"./IncompleteDownloads-BiPaaahS.js";import{t as ne}from"./LicenseButton-D3VmcVG1.js";var p=e(t(),1),m=n(),h=`Downloading knowledge catalogs needs app network access, which the security policy turns off (Settings → Security).`;function g(e){return e instanceof Error?e.message:String(e)}function _(e){return e instanceof r&&e.status===403?h:`download failed: ${g(e)}`}function re(e){return e.disabledReason?`quarantined — ${e.disabledReason}`:e.enabled?e.mounted?e.vectorCompatible===!1?`active · keyword search only`:`active`:`enabled (not mounted)`:`disabled`}function ie(e){return e.semanticSearch===`keyword-only`||e.vectorCompatible===!1?`Keyword only`:`Semantic`}function v(e){let t=new Date(e);return Number.isNaN(t.getTime())?null:t.toLocaleDateString(void 0,{year:`numeric`,month:`short`})}function y(e){if(e.error)return e.error;if(e.retrying){let t=Math.max(1,Math.round(e.retrying.delayMs/1e3));return`${e.retrying.reason} — retrying in ${t}s (attempt ${e.retrying.attempt}/${e.retrying.maxAttempts})`}switch(e.phase){case`download`:return e.bytesTotal>0?`Downloading ${l(e.bytesDone)} of ${l(e.bytesTotal)}`:e.bytesDone>0?`Downloading ${l(e.bytesDone)}…`:`Preparing download…`;case`retrying`:return`Connection dropped — retrying…`;case`verifying`:return`Checking download…`;case`extract`:return`Unpacking and verifying the catalog…`;case`embedder`:return`Fetching the search model for this catalog…`}}function b(e){return e.error||e.retrying||e.phase!==`download`||e.bytesTotal<=0?null:e.bytesDone/e.bytesTotal*100}function ae(e){return e.kind===`knowledge-catalog`?e:null}function x(e){let t=e.trim();if(!t)return null;if(/^https?:\/\//i.test(t))try{let e=new URL(t);if((e.protocol===`http:`||e.protocol===`https:`)&&e.hostname)return`url`}catch{}if(!/\.gezk$/i.test(t))return null;let n=/^[a-z]:[\\/]/i.test(t),r=/^(?:\\\\|\/\/)[^\\/]+[\\/][^\\/]+/.test(t),i=t.startsWith(`/`);return n||r||i?`file`:null}function S(){let[e,t]=(0,p.useState)(null),[n,r]=(0,p.useState)(new Map),[h,S]=(0,p.useState)([]),[C,w]=(0,p.useState)(new Map),[T,E]=(0,p.useState)(null),[D,O]=(0,p.useState)(null),[k,A]=(0,p.useState)(null),[j,M]=(0,p.useState)(null),[N,P]=(0,p.useState)(``),[F,I]=(0,p.useState)(``),[L,R]=(0,p.useState)(null),z=(0,p.useRef)(!1),B=(0,p.useCallback)(async()=>{try{let[e,n,a]=await Promise.all([i.listKnowledgeCatalogs(),i.listAvailableKnowledgeCatalogs().catch(()=>({catalogs:[]})),i.listIncompleteKnowledgeDownloads().catch(()=>({incomplete:[]}))]);t(e.catalogs),r(new Map(n.catalogs.map(e=>[e.id,e]))),S(a.incomplete)}catch(e){M(g(e))}},[]);(0,p.useEffect)(()=>{B();let e=e=>{o(e)===`knowledge`&&B()};return window.addEventListener(c,e),()=>window.removeEventListener(c,e)},[B]),(0,p.useEffect)(()=>{let e=!1,t=async()=>{try{let t=await i.listKnowledgeActiveInstalls();if(e)return;w(e=>{let n=new Map(e),r=new Set;for(let e of t.installs)r.add(e.jobId),n.get(e.jobId)?.origin!==`local`&&n.set(e.jobId,{jobId:e.jobId,...e.catalogId?{catalogId:e.catalogId}:{},phase:e.phase,bytesDone:e.bytesDone,bytesTotal:e.bytesTotal,origin:`remote`});for(let[e,t]of n)t.origin===`remote`&&!r.has(e)&&n.delete(e);return n});let n=z.current;z.current=t.installs.length>0,n&&t.installs.length===0&&B()}catch{}};t();let n=setInterval(()=>void t(),2e3);return()=>{e=!0,clearInterval(n)}},[B]);let V=(0,p.useCallback)((e,t)=>{if(t.type===`progress`)w(n=>{let r=n.get(e);if(!r)return n;let i=new Map(n),{retrying:a,error:o,...s}=r;return i.set(e,{...s,phase:t.phase,bytesDone:t.bytesDone,bytesTotal:t.bytesTotal||(t.phase===r.phase?r.bytesTotal:0)}),i});else if(t.type===`retrying`)w(n=>{let r=n.get(e);if(!r)return n;let i=new Map(n);return i.set(e,{...r,retrying:{attempt:t.attempt,maxAttempts:t.maxAttempts,delayMs:t.delayMs,reason:t.reason}}),i});else if(t.type===`verifying`)w(t=>{let n=t.get(e);if(!n)return t;let r=new Map(t);return r.set(e,{...n,phase:`verifying`}),r});else if(t.type===`done`)t.warning&&O({id:t.ref.catalogId,message:t.warning});else if(t.type===`error`){if(t.mismatch){w(t=>{let n=new Map(t);return n.delete(e),n}),A({id:e,...t.mismatch});return}w(n=>{let r=n.get(e);if(!r)return n;let i=new Map(n);return i.set(e,{...r,error:t.error,retrying:void 0}),i}),E(t.error)}},[]),H=(0,p.useCallback)(e=>{w(t=>{let n=new Map(t),r=n.get(e);return r?.error?(n.set(e,{...r,controller:void 0}),n):(n.delete(e),n)}),s(`knowledge`),B()},[B]),U=(0,p.useCallback)((e,t,n)=>{if(t.signal.aborted)return;let r=_(n);E(r),w(t=>{let n=t.get(e);if(!n)return t;let i=new Map(t);return i.set(e,{...n,error:n.error??r,retrying:void 0}),i})},[]),W=(0,p.useCallback)((e,t)=>{if(C.has(e))return;E(null),A(null);let n=new AbortController;w(t=>{let r=new Map(t);return r.set(e,{jobId:e,catalogId:e,phase:`download`,bytesDone:0,bytesTotal:0,origin:`local`,controller:n}),r}),(async()=>{try{await i.installKnowledgeCatalogFromCatalog(e,t=>V(e,t),n.signal,t?.version?{version:t.version}:void 0)}catch(t){U(e,n,t)}finally{H(e)}})()},[C,V,U,H]),G=(0,p.useCallback)(async e=>{E(null),A(null);let t;try{({jobId:t}=await i.installKnowledgeCatalog({source:e}))}catch(e){E(_(e));return}let n=new AbortController;w(r=>{let i=new Map(r);return i.set(t,{jobId:t,phase:e.kind===`file`?`verifying`:`download`,bytesDone:0,bytesTotal:0,origin:`local`,controller:n,source:e}),i});try{await i.subscribeKnowledgeInstall(t,e=>V(t,e),n.signal),P(``),I(``)}catch(e){U(t,n,e)}finally{H(t)}},[V,U,H]),K=(0,p.useCallback)(e=>{C.get(e)?.controller?.abort(),i.cancelKnowledgeJob(e).catch(()=>{}),w(t=>{let n=new Map(t);return n.delete(e),n}),B()},[C,B]),q=(0,p.useCallback)(e=>{w(t=>{let n=new Map(t);return n.delete(e.jobId),n}),E(null),e.catalogId?W(e.catalogId):e.source&&G(e.source)},[W,G]),J=(0,p.useCallback)(async e=>{let t=e.trim(),n=x(t);if(!n)return;M(null);let r=F.trim().toLowerCase();if(n===`url`&&!/^[a-f0-9]{64}$/.test(r)){M(`Paste the publisher-provided SHA-256 digest before installing a URL.`);return}await G(n===`url`?{kind:`url`,url:t,expectedSha256:r}:{kind:`file`,path:t})},[F,G]),oe=(0,p.useCallback)(async()=>{let e=await window.__GEZEL__?.selectKnowledgeArchive?.();e&&(P(e),await J(e))},[J]),se=(0,p.useCallback)(async(e,t)=>{M(null);try{await i.updateKnowledgeCatalog(e,{enabled:t})}catch(e){M(g(e))}s(`knowledge`),await B()},[B]),Y=(0,p.useCallback)(async e=>{R(null),M(null);try{await i.removeKnowledgeCatalog(e)}catch(e){M(g(e))}s(`knowledge`),await B()},[B]),ce=(0,p.useCallback)(async e=>{M(null),S(t=>t.filter(t=>t.key!==e));try{await i.deleteIncompleteKnowledgeDownload(e)}catch(e){M(g(e))}await B()},[B]),le=(0,p.useMemo)(()=>h.filter(e=>!(e.catalogId&&C.has(e.catalogId))).map(e=>({id:e.key,name:e.name??e.catalogId??e.key,bytes:e.bytes,updatedAt:e.updatedAt,hasPartial:!0,resumable:e.resumable})),[h,C]),ue=(0,p.useMemo)(()=>new Map(h.map(e=>[e.key,e])),[h]),X=e?.find(e=>e.ref.catalogId===L),Z=x(N),Q=Z===`url`,de=/^[a-fA-F0-9]{64}$/.test(F.trim()),fe=[...C.values()].some(e=>e.source&&!e.error),$=Z!==null&&(!Q||de)&&!fe;return(0,m.jsxs)(`div`,{className:`ollama-model-manager`,"data-testid":`knowledge-catalog-manager`,children:[C.size>0&&(0,m.jsxs)(`div`,{className:`ollama-section`,children:[(0,m.jsx)(`h4`,{children:`Downloading…`}),(0,m.jsx)(`div`,{className:`ollama-pull-list`,children:Array.from(C.values()).map(e=>(0,m.jsx)(f,{title:(0,m.jsx)(`code`,{children:e.catalogId??e.source?.kind??e.jobId}),status:y(e),percent:b(e),tone:e.error?`error`:e.retrying?`warning`:`normal`,onCancel:()=>K(e.jobId),...e.catalogId||e.source?{onRetry:()=>q(e)}:{}},e.jobId))})]}),(0,m.jsx)(te,{items:le,onResume:e=>{let t=ue.get(e);t?.catalogId&&W(t.catalogId)},onDelete:e=>void ce(e)}),k&&(0,m.jsxs)(`div`,{className:`ollama-section`,children:[(0,m.jsxs)(`div`,{className:`gz-status-pill gz-status-pill--warn`,style:{marginBottom:`0.5rem`},children:[`The download of `,(0,m.jsx)(`code`,{children:k.id}),` did not match the catalog's pinned checksum`]}),(0,m.jsx)(`p`,{style:{marginBottom:`0.5rem`},children:`Nothing was installed. The bytes Gezel received are not the release this build's catalog vouches for, so either the catalog entry is wrong or the download was tampered with. Try again later, or wait for a Gezel update with a refreshed catalog.`}),(0,m.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:()=>A(null),children:`Dismiss`})]}),T&&(0,m.jsx)(`div`,{className:`ollama-section`,children:(0,m.jsx)(`p`,{className:`error`,style:{marginBottom:`0.5rem`},children:T})}),D&&(0,m.jsx)(`div`,{className:`ollama-section`,children:(0,m.jsxs)(`div`,{className:`gz-status-pill gz-status-pill--warn`,style:{marginBottom:`0.5rem`},children:[D.id,`: `,D.message]})}),(0,m.jsxs)(`div`,{className:`ollama-section`,children:[(0,m.jsx)(`h4`,{children:`Installed catalogs`}),e===null&&(0,m.jsx)(`p`,{className:`muted small`,children:`loading…`}),e?.length===0&&(0,m.jsxs)(`p`,{className:`muted small`,children:[`Nothing installed yet. Download one below, build one from a folder of Markdown with`,` `,(0,m.jsx)(`code`,{children:`gezel knowledge init`}),` and `,(0,m.jsx)(`code`,{children:`gezel knowledge build`}),`, or install a published .gezk file.`]}),e&&e.length>0&&(0,m.jsx)(`div`,{className:`ollama-model-table-wrap`,children:(0,m.jsxs)(`table`,{className:`ollama-model-table`,children:[(0,m.jsx)(`thead`,{children:(0,m.jsxs)(`tr`,{children:[(0,m.jsx)(`th`,{children:`Name`}),(0,m.jsx)(`th`,{children:`Version`}),(0,m.jsx)(`th`,{children:`Documents`}),(0,m.jsx)(`th`,{children:`Size`}),(0,m.jsx)(`th`,{title:`Semantic search embeds your question with the catalog's own model; keyword-only catalogs match words`,children:`Search`}),(0,m.jsx)(`th`,{children:`Storage`}),(0,m.jsx)(`th`,{children:`Status`}),(0,m.jsx)(`th`,{children:`Enabled`}),(0,m.jsx)(`th`,{})]})}),(0,m.jsx)(`tbody`,{children:e.map(e=>{let t=C.has(e.ref.catalogId);return(0,m.jsxs)(`tr`,{"data-testid":`knowledge-catalog-${e.ref.catalogId}`,children:[(0,m.jsx)(`td`,{className:`model-name-table-cell`,children:(0,m.jsxs)(`div`,{className:`model-name-cell`,children:[(0,m.jsx)(`strong`,{children:e.name??e.ref.catalogId}),(0,m.jsxs)(`div`,{className:`model-name-meta`,children:[(0,m.jsx)(`code`,{children:e.ref.catalogId}),e.language&&(0,m.jsx)(`span`,{className:`muted small`,children:e.language}),e.updateAvailable&&(0,m.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,title:`A newer release is available in the catalog (→ v${e.availableVersion??``}).`,children:`update available`})]})]})}),(0,m.jsxs)(`td`,{children:[`v`,e.ref.version]}),(0,m.jsx)(`td`,{children:e.documents===void 0?`—`:e.documents.toLocaleString()}),(0,m.jsx)(`td`,{children:e.sizeBytes?l(e.sizeBytes):`—`}),(0,m.jsx)(`td`,{children:e.mounted?ie(e):`—`}),(0,m.jsx)(`td`,{title:e.ref.storageScope===`machine-shared`?`Installed once for everyone on this device; removing it only drops it from your account.`:`Stored in your own home folder.`,children:e.ref.storageScope===`machine-shared`?`Shared on this device`:`Only for you`}),(0,m.jsx)(`td`,{className:e.disabledReason?`error`:void 0,children:re(e)}),(0,m.jsx)(`td`,{children:(0,m.jsx)(`input`,{type:`checkbox`,"aria-label":`Enable ${e.name??e.ref.catalogId}`,checked:e.enabled,onChange:t=>void se(e.ref.catalogId,t.target.checked)})}),(0,m.jsx)(`td`,{className:`model-actions-table-cell`,children:(0,m.jsxs)(`div`,{className:`model-action-links`,children:[e.updateAvailable&&e.source===`gilde`&&(0,m.jsx)(`button`,{type:`button`,className:`gz-link-button`,disabled:t,onClick:()=>W(e.ref.catalogId),children:`Update`}),(0,m.jsx)(`button`,{type:`button`,className:`gz-link-button danger`,disabled:t,onClick:()=>R(e.ref.catalogId),children:`Remove`})]})})]},e.ref.catalogId)})})]})})]}),(0,m.jsxs)(`div`,{className:`ollama-section ollama-section--flat ollama-section--download`,children:[(0,m.jsx)(`h4`,{children:`Download a catalog`}),(0,m.jsxs)(`p`,{className:`muted small`,style:{marginTop:0},children:[`Knowledge catalogs are hosted by`,` `,(0,m.jsx)(`a`,{href:`https://huggingface.co`,target:`_blank`,rel:`noreferrer`,style:{color:`inherit`},children:`Hugging Face`}),` `,`as open datasets in the gezk format. Your device downloads them directly and checks every byte against the checksum this version of Gezel pinned.`]}),(0,m.jsx)(u,{kind:`knowledge-catalog`,emptyMessage:`No knowledge catalogs in the catalog for this build yet.`,action:e=>{let t=ae(e.manifest);if(!t)return null;let r=n.get(t.id),i=C.get(t.id),a=i?b(i):null,o=r?.installed,s=o?.updateAvailable??!1,c=!!i||!!o&&!s,u=i?i.phase===`download`?a===null?`Downloading…`:`Downloading… ${Math.round(a)}%`:i.phase===`embedder`?`Fetching search model…`:`Installing…`:o?s?`Update to v${t.version}`:`Installed`:r?.incompleteDownload?`Resume download`:r?.sharedOnDevice?`Add`:`Download`,f=v(t.releasedAt);return(0,m.jsxs)(`div`,{className:`catalog-ollama-action`,children:[(0,m.jsxs)(`div`,{className:`catalog-ollama-meta`,children:[(0,m.jsxs)(`div`,{className:`catalog-ollama-specs muted small`,children:[(0,m.jsx)(ee,{repo:t.huggingface.repo,repoType:`dataset`}),(0,m.jsx)(`span`,{children:`·`}),(0,m.jsx)(`span`,{children:l(t.archiveBytes)}),(0,m.jsx)(`span`,{children:`·`}),(0,m.jsxs)(`span`,{children:[t.documents.toLocaleString(),` documents`]}),(0,m.jsx)(`span`,{children:`·`}),(0,m.jsx)(`span`,{children:t.language}),f&&(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(`span`,{children:`·`}),(0,m.jsx)(`span`,{children:f})]})]}),(0,m.jsxs)(`div`,{className:`catalog-ollama-pills`,children:[(0,m.jsx)(ne,{manifest:t,fallbackHref:d(t.huggingface.repo,`dataset`)}),t.parquet&&(0,m.jsx)(`a`,{className:`hf-repo-link`,href:`${d(t.parquet.repo,`dataset`)}/tree/${encodeURIComponent(t.parquet.revision)}/${t.parquet.dir.split(`/`).map(encodeURIComponent).join(`/`)}`,target:`_blank`,rel:`noreferrer`,title:`The same documents, chunks and embeddings as Parquet tables, for data tools`,children:`Parquet`}),r?.sharedOnDevice&&!o&&(0,m.jsx)(`span`,{className:`gz-status-pill gz-status-pill--ok`,title:`Another account on this device already installed it; adding it to yours takes no download.`,children:`on this device`})]})]}),(0,m.jsx)(`button`,{type:`button`,disabled:c,title:o&&!s?`Installed (v${o.version})`:r?.incompleteDownload?`A partial download is on disk; installing picks up where it stopped.`:void 0,onClick:()=>W(t.id),children:u})]})}})]}),(0,m.jsxs)(`div`,{className:`ollama-section ollama-section--flat`,children:[(0,m.jsx)(`h4`,{children:`Add from a file or URL`}),(0,m.jsxs)(`div`,{className:`new-row`,style:{alignItems:`center`},children:[(0,m.jsx)(`input`,{type:`text`,style:{flex:1},placeholder:`Path to a .gezk file, or an https:// URL`,"aria-label":`Catalog file path or URL`,value:N,onChange:e=>P(e.target.value),onKeyDown:e=>{e.key===`Enter`&&$&&J(N)}}),window.__GEZEL__?.selectKnowledgeArchive&&(0,m.jsx)(`button`,{type:`button`,onClick:()=>void oe(),children:`Browse…`}),Z!==null&&(0,m.jsx)(`button`,{type:`button`,disabled:!$,onClick:()=>void J(N),children:`Install`})]}),Q&&(0,m.jsxs)(`div`,{style:{marginTop:`0.5rem`},children:[(0,m.jsx)(`input`,{type:`text`,style:{width:`100%`},placeholder:`Publisher SHA-256 digest (64 hexadecimal characters)`,"aria-label":`Catalog SHA-256 digest`,value:F,spellCheck:!1,autoCapitalize:`none`,onChange:e=>I(e.target.value),onKeyDown:e=>{e.key===`Enter`&&$&&J(N)}}),(0,m.jsx)(`p`,{className:`muted small`,style:{margin:`0.35rem 0 0`},children:`Remote catalogs are installed only when their bytes match a SHA-256 digest you received from the publisher.`})]})]}),j&&(0,m.jsx)(`p`,{className:`error small`,children:j}),(0,m.jsx)(a,{open:L!==null,title:`Remove ${X?.name??L??``}?`,message:X?.ref.storageScope===`machine-shared`?`Removes this catalog from your account. The shared copy other people on this device use is not touched.`:X?.source===`gilde`?`Deletes this catalog and its files from your account. You can download it again from the catalog any time.`:`Deletes this catalog and its files from your account. If you built it yourself and no longer have the .gezk, this is the only copy.`,confirmLabel:`Remove catalog`,danger:!0,onConfirm:()=>{L&&Y(L)},onCancel:()=>R(null)})]})}function C(){return(0,m.jsxs)(`section`,{style:{marginBottom:`2rem`},"data-testid":`knowledge-settings`,children:[(0,m.jsx)(`h3`,{children:`Knowledge`}),(0,m.jsx)(`p`,{className:`muted`,style:{marginTop:0},children:`Knowledge catalogs are searchable, citable reference libraries — encyclopedias, manuals, your own notes — packaged as .gezk files. Installed catalogs appear in the Knowledge area and your gezellen can search them and cite their sources. Everything stays on this device.`}),(0,m.jsx)(S,{})]})}export{C as KnowledgeCatalogsCard};
@@ -0,0 +1 @@
1
+ import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{n as t,t as n}from"./jsx-runtime-CEpd2cAX.js";import{wn as r}from"./dist-BqGwkOe5.js";import{t as i}from"./api-BPraLwsh.js";import{i as ee,t as a}from"./model-inventory-ykSm_IT5.js";import{ft as o}from"./doc-Dr5K49bx.js";import{n as s}from"./chunk-UBFT2CDQ-FexGDigd.js";import"./markdown-ryKA_OmY.js";import{z as c}from"./chunk-6ECMNUIP-DDVjPyfK.js";import{M as l,N as u,U as d,gt as f,ht as p,q as te}from"./index-C0DYtvfg.js";import{n as m}from"./composer-prefill-CbG_i1Rx.js";var h=e(t(),1),g=n(),_=`gezel:knowledge:catalog`,v=`gezel:knowledge:document`,y=50;function b(e){let t=new Map(e.map(e=>[e.id,{...e,children:[]}])),n=[];for(let e of t.values()){let r=e.parentId?t.get(e.parentId):void 0;r?r.children.push(e):n.push(e)}return n}function x(){let[e,t]=(0,h.useState)(null),[n,x]=(0,h.useState)(()=>{try{return window.localStorage.getItem(_)}catch{return null}}),[S,C]=(0,h.useState)([]),[w,T]=(0,h.useState)(null),[E,D]=(0,h.useState)(null),[O,ne]=(0,h.useState)(0),[k,A]=(0,h.useState)(!1),[j,M]=(0,h.useState)(()=>{try{return window.localStorage.getItem(v)}catch{return null}}),[N,P]=(0,h.useState)(null),[re,F]=(0,h.useState)(!1),[I,L]=(0,h.useState)(null),[R,z]=(0,h.useState)(``),[B,V]=(0,h.useState)(null),[H,U]=(0,h.useState)(!1),[W,G]=(0,h.useState)(!1),K=(0,h.useRef)(null),q=p()===`light`?l:void 0;(0,h.useEffect)(()=>{let e=!0,n=te();n&&(x(n.catalogId),n.documentId&&M(n.documentId));let r=()=>{i.listKnowledgeCatalogs().then(n=>{if(!e)return;let r=n.catalogs.filter(e=>e.mounted);t(r),x(e=>(e&&r.some(t=>t.ref.catalogId===e)?e:null)??r[0]?.ref.catalogId??null)}).catch(()=>{e&&t([])})};r();let o=e=>{ee(e)===`knowledge`&&r()};window.addEventListener(a,o);let s=e=>{let t=e.detail;t?.catalogId&&(x(t.catalogId),t.documentId&&M(t.documentId))};return window.addEventListener(`gezel:open-knowledge-document`,s),()=>{e=!1,window.removeEventListener(a,o),window.removeEventListener(`gezel:open-knowledge-document`,s)}},[]),(0,h.useEffect)(()=>{try{n&&window.localStorage.setItem(_,n)}catch{}},[n]),(0,h.useEffect)(()=>{if(!n)return;let e=!0;return C([]),T(null),i.knowledgeCatalogTopics(n).then(t=>{e&&C(t.topics)}).catch(()=>{}),()=>{e=!1}},[n]);let J=(0,h.useCallback)(async e=>{if(!n)return;let t=await i.knowledgeCatalogDocuments(n,{...w?{topicId:w}:{},offset:e,limit:y});ne(t.total),D(n=>e===0||!n?t.documents:[...n,...t.documents])},[n,w]);(0,h.useEffect)(()=>{D(null),J(0).catch(()=>D([]))},[J]),(0,h.useEffect)(()=>{if(!n||!j){P(null);return}let e=!0;F(!0),L(null),i.readKnowledgeDocument(n,j).then(t=>{e&&P(t)}).catch(t=>{e&&L(t instanceof Error?t.message:String(t))}).finally(()=>{e&&F(!1)});try{window.localStorage.setItem(v,j)}catch{}return()=>{e=!1}},[n,j]),(0,h.useEffect)(()=>{K.current&&window.clearTimeout(K.current);let e=R.trim();if(!e){V(null),U(!1);return}return U(!0),K.current=window.setTimeout(()=>{i.searchKnowledge({query:e,maxResults:20,...n?{catalogs:[n]}:{}}).then(e=>{V(e.results)}).catch(()=>{V([])}).finally(()=>U(!1))},250),()=>{K.current&&window.clearTimeout(K.current)}},[R,n]);let Y=(0,h.useMemo)(()=>e?.find(e=>e.ref.catalogId===n)??null,[e,n]),ie=(0,h.useMemo)(()=>b(S),[S]),X=(0,h.useMemo)(()=>new Map(S.map(e=>[e.id,e.name])),[S]),Z=(0,h.useMemo)(()=>{if(!N)return null;try{return o(s(N.markdown),{articleId:N.id})}catch{return null}},[N]),Q=(0,h.useMemo)(()=>{if(!n||!N)return null;let t=e?.find(e=>e.ref.catalogId===n)?.ref.publisherId;return t?r({publisherId:t,catalogId:n,documentId:N.id}):null},[e,n,N]),ae=(0,h.useCallback)(()=>{Q&&navigator.clipboard?.writeText(Q).then(()=>{G(!0),window.setTimeout(()=>G(!1),2e3)})},[Q]),oe=(0,h.useCallback)(()=>{!Q||!N||(m(`default`,`I'm reading "${N.title}" (${Q}). Can you help me with a question about it?\n\n`),d({kind:`project`,id:`default`}))},[Q,N]),se=(0,h.useCallback)(()=>{f(`knowledge`),d({kind:`area`,area:`settings`})},[]);if(e!==null&&e.length===0)return(0,g.jsx)(`div`,{className:`knowledge-view`,"data-testid":`knowledge-view`,children:(0,g.jsxs)(`div`,{className:`knowledge-empty`,style:{gridColumn:`1 / -1`},children:[(0,g.jsx)(`h2`,{children:`Knowledge`}),(0,g.jsx)(`p`,{className:`muted`,children:`No knowledge catalogs are installed yet. A catalog is a searchable, citable reference library — install one and your gezellen can look things up and cite their sources.`}),(0,g.jsx)(`button`,{type:`button`,onClick:se,children:`Open knowledge settings`})]})});let $=(e,t)=>(0,g.jsxs)(`li`,{children:[(0,g.jsxs)(`button`,{type:`button`,className:`knowledge-topic-row`,"aria-current":w===e.id?`true`:void 0,onClick:()=>{T(t=>t===e.id?null:e.id),z(``)},children:[(0,g.jsx)(`span`,{children:e.name}),(0,g.jsx)(`span`,{className:`knowledge-topic-count`,children:e.documentCount})]}),e.children.length>0&&(0,g.jsx)(`ul`,{children:e.children.map(e=>$(e,t+1))})]},e.id);return(0,g.jsxs)(`div`,{className:`knowledge-view`,"data-testid":`knowledge-view`,children:[(0,g.jsxs)(`nav`,{className:`knowledge-rail`,"aria-label":`Knowledge catalogs and topics`,children:[e&&e.length>1&&(0,g.jsx)(`select`,{"aria-label":`Catalog`,value:n??``,onChange:e=>{x(e.target.value),M(null)},children:e.map(e=>(0,g.jsx)(`option`,{value:e.ref.catalogId,children:e.name??e.ref.catalogId},e.ref.catalogId))}),Y&&(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`h2`,{className:`knowledge-catalog-name`,children:Y.name??n}),(0,g.jsxs)(`p`,{className:`knowledge-catalog-meta`,children:[Y.documents??`?`,` documents · `,Y.license??``,Y.ref.version?` · v${Y.ref.version}`:``]})]}),(0,g.jsx)(`input`,{type:`search`,className:`knowledge-rail-search`,placeholder:`Search this catalog…`,"aria-label":`Search knowledge`,value:R,onChange:e=>z(e.target.value)}),(0,g.jsx)(`ul`,{className:`knowledge-topics`,children:ie.map(e=>$(e,0))})]}),(0,g.jsx)(`section`,{className:`knowledge-list`,"aria-label":`Documents`,children:R.trim()?(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`div`,{className:`knowledge-list-header`,children:`Search results`}),H&&(0,g.jsx)(`p`,{className:`muted small`,style:{padding:`0 1rem`},children:`Searching…`}),!H&&B?.length===0&&(0,g.jsxs)(`p`,{className:`muted small`,style:{padding:`0 1rem`},children:[`No results for “`,R.trim(),`”.`]}),(0,g.jsx)(`ul`,{className:`knowledge-doc-list`,children:(B??[]).map(e=>(0,g.jsx)(`li`,{children:(0,g.jsxs)(`button`,{type:`button`,className:`knowledge-doc-row`,"aria-current":e.documentId===j?`true`:void 0,onClick:()=>{e.documentId&&M(e.documentId)},children:[(0,g.jsx)(`span`,{className:`knowledge-doc-title`,children:e.title}),e.snippet&&(0,g.jsx)(`span`,{className:`knowledge-doc-summary`,children:e.snippet})]})},e.id))})]}):(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`div`,{className:`knowledge-list-header`,children:w?X.get(w)??`Documents`:`All documents`}),E===null&&(0,g.jsx)(`p`,{className:`muted small`,style:{padding:`0 1rem`},children:`Loading…`}),(0,g.jsx)(`ul`,{className:`knowledge-doc-list`,children:(E??[]).map(e=>(0,g.jsx)(`li`,{children:(0,g.jsxs)(`button`,{type:`button`,className:`knowledge-doc-row`,"aria-current":e.id===j?`true`:void 0,onClick:()=>M(e.id),children:[(0,g.jsx)(`span`,{className:`knowledge-doc-title`,children:e.title}),e.summary&&(0,g.jsx)(`span`,{className:`knowledge-doc-summary`,children:e.summary})]})},e.id))}),E&&E.length<O&&(0,g.jsx)(`button`,{type:`button`,className:`knowledge-list-more`,disabled:k,onClick:()=>{A(!0),J(E.length).finally(()=>A(!1))},children:k?`Loading…`:`Show more (${O-E.length} left)`})]})}),(0,g.jsx)(`section`,{className:`knowledge-reader`,"aria-label":`Article`,children:N?(0,g.jsxs)(g.Fragment,{children:[(0,g.jsxs)(`header`,{className:`knowledge-reader-header`,children:[(0,g.jsx)(`h2`,{children:N.title}),(0,g.jsxs)(`p`,{className:`knowledge-reader-meta`,children:[X.get(N.topicId)??N.topicId,N.sourceUpdatedAt?` · snapshot ${N.sourceUpdatedAt.slice(0,10)}`:``]})]}),(0,g.jsx)(`div`,{className:`knowledge-reader-body`,children:Z?(0,g.jsx)(c,{doc:Z,className:`gezel-article-view`,theme:u,...q?{surface:q}:{},imageDisplayMode:`inline`,showCover:!1}):(0,g.jsx)(`p`,{className:`error small`,children:`This document could not be rendered.`})}),(0,g.jsxs)(`footer`,{className:`knowledge-reader-footer`,children:[(0,g.jsxs)(`span`,{children:[Y?.license??``,N.attribution?.text?` · ${N.attribution.text}`:``]}),(0,g.jsxs)(`span`,{className:`knowledge-footer-actions`,children:[(0,g.jsx)(`button`,{type:`button`,onClick:ae,children:W?`Copied`:`Copy citation`}),N.sourceUrl&&(0,g.jsx)(`a`,{href:N.sourceUrl,target:`_blank`,rel:`noreferrer`,children:(0,g.jsx)(`button`,{type:`button`,children:`Open source`})}),(0,g.jsx)(`button`,{type:`button`,onClick:oe,children:`Ask a gezel about this`})]})]})]}):(0,g.jsx)(`div`,{className:`knowledge-empty`,children:re?(0,g.jsx)(`p`,{className:`muted`,children:`Loading…`}):I?(0,g.jsx)(`p`,{className:`error`,children:I}):(0,g.jsx)(`p`,{className:`placeholder`,children:`Pick a document on the left to read it here.`})})})]})}export{x as KnowledgeView};
@@ -0,0 +1 @@
1
+ import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{n as t,t as n}from"./jsx-runtime-CEpd2cAX.js";import{A as r,H as i,Jt as a,P as o,St as s,U as c,_t as l,ot as u,pt as d}from"./dist-BqGwkOe5.js";import{t as f}from"./api-BPraLwsh.js";import{t as p}from"./model-context-DBqdK0PS.js";import{r as m}from"./model-memory-copy-CeuXAj-T.js";import{t as h}from"./ConfirmDialog-Dt1ed4Fh.js";import{a as g,r as _,t as v}from"./model-inventory-ykSm_IT5.js";import{wt as y}from"./index-C0DYtvfg.js";import{t as b}from"./CatalogBrowser-DEM9t7Es.js";import{n as x,r as S,t as C}from"./InstallProgressRow-DyKOI4MU.js";import{t as w}from"./IncompleteDownloads-BiPaaahS.js";import{t as ee}from"./LicenseButton-D3VmcVG1.js";import{a as T,i as te,n as ne,o as E,r as re,t as ie}from"./UnrecognizedModels-HtdMZUqK.js";import{t as D}from"./local-engine-label-BR-PGVFE.js";import{n as O,r as k,t as ae}from"./model-quantization-CLO7XLoF.js";var A=e(t(),1),j=n();function M(e){return{usableBytes:e.usableBytes,totalRamBytes:e.totalRamBytes,gpuVramBytes:e.gpuMemoryKind===`integrated`?null:e.gpuVramBytes,...e.budgetBytes===void 0?{}:{admissibleBytes:e.budgetBytes}}}function N(e,t){let{totalRamBytes:n,gpuVramBytes:r}=M(t);return c(e,{ctxTokens:s({totalRamBytes:n,gpuVramBytes:r})})}function oe(e,t){return o({residentBytes:i(e.llamaCpp.approxSizeBytes,{mmprojBytes:e.llamaCpp.mmproj?.sizeBytes})+N(e,t),isMoE:d(e.tags),...M(t)})}function se(e){return{platform:e.source===`darwin-unified`?`darwin`:`other`,gpuVramBytes:e.gpuVramBytes,...e.gpuMemoryKind?{gpuMemoryKind:e.gpuMemoryKind}:{},totalRamBytes:e.totalRamBytes,usableBytes:e.usableBytes,...e.budgetBytes===void 0?{}:{budgetBytes:e.budgetBytes}}}function ce(e){return`~${m(e)}`}function P(e){if(!e)return null;let t=new Date(e);return Number.isNaN(t.getTime())?null:t.toLocaleDateString(void 0,{year:`numeric`,month:`short`})}function F(e){return e.kind!==`chat-model`||!e.llamaCpp?null:e}var le={"mix of experts":`Only a fraction of the model's parameters run per token, so it's faster than a dense model of the same nominal size.`,vision:`Can accept images alongside text.`,tools:`Supports function/tool calling via the API.`,multimodal:`Handles multiple input types (text + images).`,large:`Heavy model — needs a lot of memory and runs more slowly.`,small:`Compact model — runs quickly on modest hardware.`};function I({onModelsChanged:e,compact:t=!1}){let[n,s]=(0,A.useState)([]),[c,m]=(0,A.useState)(null),[C,D]=(0,A.useState)(!0),[O,k]=(0,A.useState)([]),[I,L]=(0,A.useState)([]),[R,z]=(0,A.useState)(new Map),[B,V]=(0,A.useState)(null),[H,U]=(0,A.useState)(null),[W,G]=(0,A.useState)(null),[K,q]=(0,A.useState)(null),[J,fe]=(0,A.useState)(null),[Y,pe]=(0,A.useState)(!1),[me,he]=(0,A.useState)(null),[ge,_e]=(0,A.useState)(null),[ve,ye]=(0,A.useState)(!1),[be,xe]=(0,A.useState)([]),[Se,Ce]=(0,A.useState)(new Map),[we,Te]=(0,A.useState)([]),Ee=(0,A.useRef)([]),X=(0,A.useRef)(null),De=(0,A.useRef)(!1),Z=(0,A.useCallback)(async()=>{try{let e=await f.listModelFitness();Ce(new Map(e.records.map(e=>[e.key,e]))),Te(e.probing),Ee.current=e.probing}catch{}},[]),Oe=(0,A.useCallback)(async(e,t)=>{_e(e);try{let n=await f.getConfig();await f.updateConfig({nativeVision:{...n.nativeVision??{},[e]:t}}),await Q()}catch{}finally{_e(null)}},[]),ke=(0,A.useCallback)(async()=>{try{let e=await f.listIncompleteLlamaCppModels();k(e.incomplete??[])}catch{}},[]),Q=(0,A.useCallback)(()=>{if(X.current)return X.current;D(!0);let e=(async()=>{try{let e=await f.listLlamaCppModels();s(e.models),L(e.unrecognized??[]),m(null)}catch(e){m(e instanceof Error?e.message:String(e))}finally{D(!1)}Z(),ke()})();return X.current=e,e.then(()=>{X.current===e&&(X.current=null)}),e},[Z,ke]);(0,A.useEffect)(()=>{Q(),f.getMemoryProfile().then(e=>fe(e)).catch(()=>{}),f.getModelContextOverrides(`llama-cpp`).then(()=>ye(!0)).catch(()=>ye(!1))},[Q]),(0,A.useEffect)(()=>{let e=e=>{g(e)===`llama-cpp`&&Q()};return window.addEventListener(v,e),()=>window.removeEventListener(v,e)},[Q]),(0,A.useEffect)(()=>{let e=!1,t=async()=>{try{let t=await f.listLlamaCppActiveInstalls();if(e)return;z(e=>{let n=new Map(e),r=new Set;for(let e of t.installs){r.add(e.catalogId);let t=n.get(e.catalogId);t&&t.origin===`local`||n.set(e.catalogId,{catalogId:e.catalogId,bytesWritten:e.bytesWritten,totalBytes:e.totalBytes,phase:e.phase,origin:`remote`})}for(let[e,t]of n)t.origin===`remote`&&!r.has(e)&&n.delete(e);return n});let n=De.current;De.current=t.installs.length>0,n&&t.installs.length===0&&Q()}catch{}};t();let n=setInterval(()=>void t(),2e3);return()=>{e=!0,clearInterval(n)}},[Q]),(0,A.useEffect)(()=>{let e=!1,t,n=async()=>{await Z(),!e&&(t=setTimeout(()=>void n(),Ee.current.length>0?2e3:15e3))};return n(),()=>{e=!0,t&&clearTimeout(t)}},[Z]);let Ae=(0,A.useCallback)((e,t)=>{if(t.type===`progress`)z(n=>{let r=n.get(e);if(!r)return n;let i=new Map(n),{retrying:a,error:o,...s}=r;return i.set(e,{...s,bytesWritten:t.bytesWritten,totalBytes:t.totalBytes||r.totalBytes,phase:`downloading`}),i});else if(t.type===`retrying`)z(n=>{let r=n.get(e);if(!r)return n;let i=new Map(n);return i.set(e,{...r,retrying:{attempt:t.attempt,maxAttempts:t.maxAttempts,delayMs:t.delayMs,reason:t.reason}}),i});else if(t.type===`verifying`)z(t=>{let n=t.get(e);if(!n)return t;let r=new Map(t);return r.set(e,{...n,phase:`verifying`}),r});else if(t.type===`extracting-metadata`)z(t=>{let n=t.get(e);if(!n)return t;let r=new Map(t);return r.set(e,{...n,phase:`extracting-metadata`}),r});else if(t.type===`done`)t.warning&&V({id:t.id,message:t.warning});else if(t.type===`error`){if(t.mismatch){let n=t.mismatch.file;z(t=>{let n=new Map(t);return n.delete(e),n}),G({catalogId:e,file:n});return}z(n=>{let r=n.get(e);if(!r)return n;let i=new Map(n);return i.set(e,{...r,error:t.error,retrying:void 0}),i}),U(t.error)}},[]),$=(0,A.useCallback)((t,n)=>{if(R.has(t))return;U(null),G(null);let r=new AbortController;z(e=>{let n=new Map(e);return n.set(t,{catalogId:t,bytesWritten:0,totalBytes:0,phase:`downloading`,origin:`local`,controller:r}),n}),(async()=>{try{await f.installLlamaCppModel(t,e=>Ae(t,e),r.signal,n?.skipSha?{skipSha:!0}:void 0),_(`llama-cpp`)}catch(e){if(!r.signal.aborted){let n=`download failed: ${de(e)}`;U(n),z(e=>{let r=e.get(t);if(!r)return e;let i=new Map(e);return i.set(t,{...r,error:r.error??n,retrying:void 0}),i})}}finally{z(e=>{let n=new Map(e),r=n.get(t);return r?.error?(n.set(t,{...r,controller:void 0}),n):(n.delete(t),n)}),Q(),e?.()}})()},[R,Q,Ae,e]),je=(0,A.useCallback)(e=>{G(null),$(e,{skipSha:!0})},[$]),Me=(0,A.useCallback)(e=>{R.get(e)?.controller?.abort(),f.cancelLlamaCppModelInstall(e).catch(()=>{}),z(t=>{let n=new Map(t);return n.delete(e),n})},[R]),Ne=(0,A.useCallback)(async()=>{let t=K;if(t){q(null),m(null),s(e=>e.filter(e=>e.id!==t)),k(e=>e.filter(e=>e.id!==t)),L(e=>e.filter(e=>e.id!==t));try{await f.deleteLlamaCppModel(t),_(`llama-cpp`),await Q(),e?.()}catch(e){m(`delete failed: ${de(e)}`),Q()}}},[K,Q,e]),Pe=(0,A.useMemo)(()=>new Set(n.map(e=>e.id)),[n]),Fe=(0,A.useMemo)(()=>new Set(I.map(e=>e.id)),[I]),Ie=(0,A.useMemo)(()=>{let e=new Map;for(let t of be){let n=F(t.manifest);n&&e.set(n.id,n)}return e},[be]);return(0,j.jsxs)(`div`,{className:`ollama-model-manager`,children:[R.size>0&&(0,j.jsxs)(`div`,{className:`ollama-section`,children:[(0,j.jsx)(`h4`,{children:`Downloading…`}),(0,j.jsx)(`div`,{className:`ollama-pull-list`,children:Array.from(R.values()).map(e=>(0,j.jsx)(ue,{inst:e,onCancel:()=>Me(e.catalogId),onRetry:()=>{z(t=>{let n=new Map(t);return n.delete(e.catalogId),n}),U(null),$(e.catalogId)}},e.catalogId))})]}),(0,j.jsx)(ie,{items:I.filter(e=>!R.has(e.id)),onUpdate:e=>$(e),onRemove:e=>q(e)}),(0,j.jsx)(w,{items:O.filter(e=>!R.has(e.id)),onResume:e=>$(e),onDelete:e=>q(e)}),W&&(0,j.jsxs)(`div`,{className:`ollama-section`,children:[(0,j.jsxs)(`div`,{className:`gz-status-pill gz-status-pill--warn`,style:{marginBottom:`0.5rem`},children:[`⚠ `,(0,j.jsx)(`code`,{children:W.catalogId}),` is newer on Hugging Face than the version Gezel knows about`]}),(0,j.jsxs)(`p`,{style:{marginBottom:`0.5rem`},children:[`The file `,(0,j.jsx)(`code`,{children:W.file}),` changed upstream, so its checksum no longer matches what this version of Gezel pinned. This is almost always a harmless upstream fix — model authors routinely re-publish chat templates and tokenizer configs — but we can't verify it automatically. You can download the current version now, or wait for a Gezel update with a refreshed catalog.`]}),(0,j.jsxs)(`div`,{style:{display:`flex`,gap:`0.75rem`},children:[(0,j.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:()=>je(W.catalogId),children:`Download anyway`}),(0,j.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:()=>G(null),children:`Dismiss`})]})]}),H&&(0,j.jsx)(`div`,{className:`ollama-section`,children:(0,j.jsx)(`p`,{className:`error`,style:{marginBottom:`0.5rem`},children:H})}),B&&(0,j.jsx)(`div`,{className:`ollama-section`,children:(0,j.jsxs)(`div`,{className:`gz-status-pill gz-status-pill--warn`,style:{marginBottom:`0.5rem`},children:[`⚠ `,B.id,`: `,B.message]})}),!t&&(0,j.jsx)(ne,{engine:`llama-cpp`,onModelsChanged:e}),(C||n.length>0||c)&&(0,j.jsxs)(`div`,{className:`ollama-section`,children:[(0,j.jsx)(`h4`,{children:t?`Models on this device`:`Local models`}),C&&n.length===0&&!c&&(0,j.jsx)(`p`,{className:`muted small`,"aria-live":`polite`,children:`Checking shared models… Large models can take a few minutes the first time; later starts use the local verification cache.`}),c&&(0,j.jsx)(`p`,{className:`error`,children:c}),n.length>0&&(0,j.jsx)(`div`,{className:`ollama-model-table-wrap`,children:(0,j.jsxs)(`table`,{className:`ollama-model-table`,children:[(0,j.jsxs)(`colgroup`,{children:[(0,j.jsx)(`col`,{className:`model-name-column`}),(0,j.jsx)(`col`,{}),(0,j.jsx)(`col`,{}),(0,j.jsx)(`col`,{}),(0,j.jsx)(`col`,{}),(0,j.jsx)(`col`,{})]}),(0,j.jsx)(`thead`,{children:(0,j.jsxs)(`tr`,{children:[(0,j.jsx)(`th`,{children:`Name`}),(0,j.jsx)(`th`,{children:`Size`}),(0,j.jsx)(`th`,{children:`Quant`}),(0,j.jsx)(`th`,{title:`Effective per-turn context size after Gezel's settings and memory limits`,children:`Context size`}),(0,j.jsx)(`th`,{title:`Representative startup and decode speed with an approximately 20K-token prompt`,children:`Fitness`}),(0,j.jsx)(`th`,{})]})}),(0,j.jsx)(`tbody`,{children:n.map(e=>{let t=R.has(e.id),n=`llama-cpp:${e.id}`,s=Se.get(n),c=Ie.get(e.id),l=e.predictedResidentBytes??i(e.approxSizeBytes,{mmprojBytes:e.mmprojSizeBytes}),m=J?o({residentBytes:l,isMoE:d(c?.tags),...M(J)}):void 0,h=J&&c?u(se(J),{isMoE:d(c.tags),fitTier:m?.tier??`fits`,residentBytes:l}):null;return(0,j.jsxs)(A.Fragment,{children:[(0,j.jsxs)(`tr`,{children:[(0,j.jsx)(`td`,{className:`model-name-table-cell`,children:(0,j.jsxs)(`div`,{className:`model-name-cell`,children:[(0,j.jsx)(`code`,{children:e.id}),(0,j.jsxs)(`div`,{className:`model-name-meta`,children:[h&&(0,j.jsx)(`span`,{className:`gz-status-pill${h.kind===`moe-good-match`?` gz-status-pill--ok`:``}`,title:h.detail,children:h.label}),e.updateAvailable&&(0,j.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,title:e.updateReason??(e.availableVersion?`A newer build is available in the catalog (→ v${e.availableVersion}). Updating downloads only the files that differ.`:`A newer build is available in the catalog.`),children:`update available`})]})]})}),(0,j.jsx)(ae,{model:e}),(0,j.jsx)(`td`,{title:a(e.quantization,e.ggufQuantization),children:r(e.quantization,e.ggufQuantization)}),(0,j.jsx)(`td`,{title:e.effectiveContextWindow?e.overrideContextTokens===void 0?`Gezel will grant up to ${e.effectiveContextWindow.toLocaleString()} tokens per turn${e.contextWindow?`; the model advertises ${e.contextWindow.toLocaleString()} tokens`:``}. The effective size accounts for model tuning, settings, concurrency, and available memory — Adaptive grows it past 64K when fast memory has room.`:`You've set this model to ${e.overrideContextTokens.toLocaleString()} tokens per turn; Gezel grants up to what memory allows (currently ${e.effectiveContextWindow.toLocaleString()}).`:e.contextSizingStatus===`restart-required`?`This model is running with a different context window than the current sizing settings resolve to. Restart the local engine (or let it go idle) so Gezel can re-admit it — no memory change needed.`:e.contextSizingStatus===`insufficient-memory`?`The selected context sizing policy needs${e.contextWindow?` this model's full advertised ${e.contextWindow.toLocaleString()}-token window`:` more context`}, which does not fit in memory safely. Choose Adaptive, unload another model, or free memory before trying again.`:`The effective context size is unavailable.`,children:e.contextSizingStatus===`restart-required`?`Restart needed`:e.contextSizingStatus===`insufficient-memory`?`Won't fit`:(0,j.jsxs)(j.Fragment,{children:[p(e.effectiveContextWindow),e.overrideContextTokens!==void 0&&(0,j.jsx)(`span`,{className:`gz-budget-tag gz-budget-tag-custom model-context-custom-tag`,children:`custom`})]})}),(0,j.jsx)(re,{entry:s,probing:we.includes(n)}),(0,j.jsx)(`td`,{className:`model-actions-table-cell`,children:(0,j.jsxs)(`div`,{className:`model-actions-cell`,children:[(0,j.jsx)(`div`,{className:`model-action-status`,children:e.readOnly&&(0,j.jsx)(`span`,{className:`muted small`,title:`Provided by the machine-wide install (shared asset store). It can't be removed from here — manage it with the machine installer, or install a user-owned copy to shadow it.`,children:`Machine model`})}),(0,j.jsx)(`div`,{className:`model-action-links`,children:(0,j.jsx)(T,{engine:`llama-cpp`,model:e,updating:t,contextSupported:ve,contextEditorOpen:me===e.id,onToggleContextEditor:()=>he(t=>t===e.id?null:e.id),...e.nativeVisionEnabled===void 0?{}:{visionAction:{enabled:e.nativeVisionEnabled,busy:ge===e.id,onToggle:()=>void Oe(e.id,!e.nativeVisionEnabled)}},fitnessAction:te(s,we.includes(n),()=>{f.runModelFitnessProbe(`llama-cpp`,e.id).then(()=>Z()).catch(()=>{})}),onUpdate:()=>$(e.id),onDelete:()=>q(e.id)})})]})})]}),me===e.id&&(0,j.jsx)(`tr`,{className:`model-context-editor-row`,children:(0,j.jsx)(`td`,{colSpan:6,children:(0,j.jsx)(E,{engine:`llama-cpp`,model:e,onSaved:Q})})})]},e.id)})})]})})]}),(0,j.jsxs)(`div`,{className:`ollama-section ollama-section--flat ollama-section--download`,children:[(0,j.jsx)(`h4`,{children:`Download a model`}),(0,j.jsxs)(`p`,{className:`muted small`,style:{marginTop:0},children:[`Models are hosted by`,` `,(0,j.jsx)(`a`,{href:`https://huggingface.co`,target:`_blank`,rel:`noreferrer`,style:{color:`inherit`},children:`Hugging Face`}),`, a community library of open, freely available AI models. Your device downloads them directly.`]}),(0,j.jsxs)(`p`,{className:`muted small`,children:[J?`Models that may not fit this machine, and retired models, are hidden by default. `:`Retired models are hidden by default. `,(0,j.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:()=>pe(e=>!e),style:{padding:0},children:Y?J?`Hide retired and oversized models`:`Hide retired models`:`Show all models`})]}),(0,j.jsx)(b,{kind:`chat-model`,emptyMessage:`No on-device models in the catalog yet.`,onItemsLoaded:xe,tagTooltips:le,filter:e=>{let t=F(e.manifest);return!(!t||!Y&&l(t)||!Y&&J&&!oe(t,J).runnable)},action:e=>{let t=F(e.manifest);if(!t)return null;let n=Pe.has(t.id),r=Fe.has(t.id),a=R.get(t.id),o=a&&a.totalBytes>0?Math.min(100,Math.round(a.bytesWritten/a.totalBytes*100)):null,s=J?oe(t,J):null;return(0,j.jsxs)(`div`,{className:`catalog-ollama-action`,children:[(0,j.jsxs)(`div`,{className:`catalog-ollama-meta`,children:[(0,j.jsxs)(`div`,{className:`catalog-ollama-specs muted small`,children:[(0,j.jsx)(x,{repo:t.llamaCpp.huggingfaceRepo}),(0,j.jsx)(`span`,{children:`·`}),(0,j.jsx)(`span`,{children:t.parameterSize}),(0,j.jsx)(`span`,{children:`·`}),(0,j.jsx)(`span`,{children:ce(t.llamaCpp.approxSizeBytes)}),P(t.releasedAt)&&(0,j.jsxs)(j.Fragment,{children:[(0,j.jsx)(`span`,{children:`·`}),(0,j.jsx)(`span`,{children:P(t.releasedAt)})]})]}),(0,j.jsxs)(`div`,{className:`catalog-ollama-pills`,children:[(0,j.jsx)(ee,{manifest:t,fallbackHref:S(t.llamaCpp.huggingfaceRepo)}),s&&s.tier!==`fits`&&(0,j.jsx)(`span`,{className:`gz-status-pill ${s.tier===`fits-offload`?`gz-status-pill--ok`:`gz-status-pill--warn`}`,title:s.detail,children:s.label}),(()=>{let n=J&&s?u(se(J),{isMoE:d(e.manifest.tags),fitTier:s.tier,residentBytes:i(t.llamaCpp.approxSizeBytes)+N(t,J)}):null;return n?(0,j.jsx)(`span`,{className:`gz-status-pill${n.kind===`moe-good-match`?` gz-status-pill--ok`:``}`,title:n.detail,children:n.label}):null})()]})]}),(0,j.jsx)(`button`,{type:`button`,disabled:n||r||!!a,onClick:()=>$(t.id),children:n?`On device`:a?a.phase===`downloading`?o===null?`Downloading…`:`Downloading… ${o}%`:a.phase===`verifying`?`Verifying…`:`Reading metadata…`:r?`Needs attention above`:`Download`})]})}})]}),(0,j.jsxs)(`div`,{className:`ollama-section ollama-section--flat`,children:[(0,j.jsx)(y,{}),(0,j.jsx)(`span`,{className:`muted small`,style:{marginLeft:`0.75rem`},children:`Import from a gezel local model package`})]}),(0,j.jsx)(h,{open:K!==null,title:`Delete ${K??``}?`,message:`This removes the downloaded model from your device. It stays available in the catalog — you can download it again any time.`,confirmLabel:`Delete`,danger:!0,onConfirm:Ne,onCancel:()=>q(null)})]})}function ue({inst:e,onCancel:t,onRetry:n}){let r=e.totalBytes>0,i=r?Math.min(100,Math.round(e.bytesWritten/e.totalBytes*100)):0,a;if(e.error)a=e.error;else if(e.retrying){let t=Math.max(1,Math.round(e.retrying.delayMs/1e3));a=`${e.retrying.reason} — retrying in ${t}s (attempt ${e.retrying.attempt}/${e.retrying.maxAttempts})`}else a=e.phase===`downloading`?r?`Downloading ${m(e.bytesWritten)} of ${m(e.totalBytes)} (${i}%)`:e.bytesWritten>0?`Downloading ${m(e.bytesWritten)}…`:`Preparing download…`:e.phase===`verifying`?`Checking download…`:`Reading model info…`;let o=e.phase!==`downloading`||!r;return(0,j.jsx)(C,{title:(0,j.jsx)(`code`,{children:e.catalogId}),status:a,percent:o?null:i,tone:e.error?`error`:e.retrying?`warning`:`normal`,onCancel:t,onRetry:n})}function de(e){return e instanceof Error?e.message:String(e)}var L=80,R=40,z=95,B=5;function V(e){return e===`win32`||e===`linux`}function H({config:e,onConfigChanged:t,platform:n}){let r=e?.deviceSafety?.mode??`observe`,i=e?.deviceSafety?.maxStartTemperatureC??L,[a,o]=(0,A.useState)(String(i)),[s,c]=(0,A.useState)(!1),[l,u]=(0,A.useState)(null);(0,A.useEffect)(()=>{o(String(i))},[i]);let d=(0,A.useCallback)(async n=>{if(!s){c(!0),u(null);try{t(await f.updateConfig({deviceSafety:{...e?.deviceSafety??{},...n}}))}catch(e){u(e instanceof Error?e.message:String(e))}finally{c(!1)}}},[e?.deviceSafety,t,s]),p=(0,A.useCallback)(e=>{r!==e&&d({mode:e})},[r,d]),m=(0,A.useCallback)(()=>{let e=Number(a);if(!Number.isInteger(e)||e<R||e>z){u(`Enter a whole number from ${R} to ${z}°C.`);return}if(e===i){u(null);return}d({maxStartTemperatureC:e,resumeTemperatureC:e-B})},[i,d,a]);if(!V(n))return null;let h=Number(a),g=(Math.min(z,Math.max(R,h))-R)/(z-R)*100;return(0,j.jsxs)(`section`,{className:`machine-health-settings`,"aria-labelledby":`machine-health-heading`,children:[(0,j.jsx)(`h4`,{id:`machine-health-heading`,children:`Machine health`}),(0,j.jsx)(`p`,{className:`muted`,style:{marginTop:0},children:`Choose whether Gezel only reports accelerator health or also waits for the machine to cool before starting new on-device work.`}),(0,j.jsxs)(`fieldset`,{className:`gz-tray machine-health-mode`,children:[(0,j.jsx)(`legend`,{className:`sr-only`,children:`Machine health mode`}),(0,j.jsxs)(`button`,{type:`button`,"aria-pressed":r===`observe`,className:`gz-key gz-key--stacked${r===`observe`?` gz-key-active`:``}`,disabled:s,onClick:()=>p(`observe`),children:[(0,j.jsx)(`span`,{children:`Observe`}),(0,j.jsx)(`small`,{children:`Report only`})]}),(0,j.jsxs)(`button`,{type:`button`,"aria-pressed":r===`guard`,className:`gz-key gz-key--stacked${r===`guard`?` gz-key-active`:``}`,disabled:s,onClick:()=>p(`guard`),children:[(0,j.jsx)(`span`,{children:`Manage`}),(0,j.jsx)(`small`,{children:`Pause new work`})]})]}),r===`off`&&(0,j.jsx)(`p`,{className:`muted small machine-health-off-note`,children:`Machine health is disabled by an advanced configuration override. Choose Observe or Manage to turn it back on.`}),(0,j.jsxs)(`div`,{className:`machine-health-temperature-row`,children:[(0,j.jsx)(`label`,{htmlFor:`machine-health-temperature`,children:`Manage temperature`}),(0,j.jsxs)(`div`,{className:`machine-health-temperature-control`,children:[(0,j.jsxs)(`div`,{className:`machine-health-temperature-slider-wrap`,children:[(0,j.jsx)(`input`,{id:`machine-health-temperature`,className:`machine-health-temperature-slider`,type:`range`,min:R,max:z,step:1,value:a,disabled:s,"aria-describedby":`machine-health-temperature-help`,"aria-valuetext":`${a} degrees Celsius`,style:{"--machine-health-temperature-progress":`${g}%`},onChange:e=>o(e.target.value),onPointerUp:e=>e.currentTarget.blur(),onBlur:m,onKeyDown:e=>{e.key===`Enter`&&e.currentTarget.blur()}}),(0,j.jsxs)(`div`,{className:`machine-health-temperature-scale`,"aria-hidden":`true`,children:[(0,j.jsxs)(`span`,{children:[R,`°`]}),(0,j.jsxs)(`span`,{className:`machine-health-temperature-default`,children:[L,`° default`]}),(0,j.jsxs)(`span`,{children:[z,`°`]})]})]}),(0,j.jsxs)(`output`,{className:`machine-health-temperature-value`,htmlFor:`machine-health-temperature`,"aria-label":`Manage temperature: ${a} degrees Celsius`,children:[(0,j.jsx)(`span`,{className:`machine-health-temperature-value-number`,children:a}),(0,j.jsx)(`span`,{"aria-hidden":`true`,children:`°C`})]})]})]}),(0,j.jsxs)(`p`,{id:`machine-health-temperature-help`,className:`muted small machine-health-temperature-help`,children:[`In Manage mode, new accelerator work waits above this temperature and resumes after a 5°C cooldown. The default is 80°C. Both modes retain the `,105,`°C emergency cutoff.`]}),s&&(0,j.jsx)(`output`,{className:`muted small machine-health-save-state`,children:`Saving…`}),l&&(0,j.jsx)(`p`,{className:`error small machine-health-save-state`,role:`alert`,children:l})]})}function U(e){return e===!0?`on`:e===!1?`off`:`auto`}function W(e,t){return e===`darwin`?[`metal`]:t===`cuda`?[`cuda`,`vulkan`,`cpu`]:t===`vulkan`?[`vulkan`,`cpu`]:t===`cpu`?[`cpu`]:[`cuda`,`vulkan`,`cpu`]}function G(e){return e===`cuda`?`CUDA (Nvidia GPU)`:e===`vulkan`?`Vulkan (any GPU)`:e===`metal`?`Metal (Apple GPU)`:`CPU only`}function K(e){return e===`amd`?`, AMD GPU detected`:e===`nvidia`?`, Nvidia GPU detected`:e===`intel`?`, Intel GPU detected`:``}function q(e,t){if(!t?.llamaCppBackend)return!1;let n=t.llamaCppBackend,r=e?.llamaCppBackendOverride&&e.llamaCppBackendOverride!==`auto`?e.llamaCppBackendOverride:t.llamaCppDetectedBackend??n;return!t.llamaCppQuarantinedBackends?.includes(r)&&r!==n}function J({config:e,onConfigChanged:t,health:n,title:r}){let[i,a]=(0,A.useState)(e?.llamaCppBaseUrl??``),[o,s]=(0,A.useState)(e?.llamaCppModelPath??``),[c,l]=(0,A.useState)([]),[u,d]=(0,A.useState)(`idle`),[p,m]=(0,A.useState)(`adaptive`),[h,g]=(0,A.useState)(!0),_=(0,A.useRef)(null),v=(0,A.useRef)(!0),y=(0,A.useCallback)(()=>{_.current!==null&&(window.clearTimeout(_.current),_.current=null)},[]);(0,A.useEffect)(()=>(v.current=!0,()=>{v.current=!1,y()}),[y]);let b=(0,A.useCallback)(e=>{v.current&&(y(),d(e))},[y]),x=(0,A.useCallback)(()=>{v.current&&(y(),d(`saved`),_.current=window.setTimeout(()=>{_.current=null,v.current&&d(`idle`)},1200))},[y]);(0,A.useEffect)(()=>{a(e?.llamaCppBaseUrl??``)},[e?.llamaCppBaseUrl]),(0,A.useEffect)(()=>{s(e?.llamaCppModelPath??``)},[e?.llamaCppModelPath]);let S=(0,A.useCallback)(async()=>{try{let e=await f.listLlamaCppModels();l(e.models)}catch{}},[]);(0,A.useEffect)(()=>{S()},[S]),(0,A.useEffect)(()=>{let e=!1;return f.getLlamaCppContextSizing().then(t=>{e||m(t.policy)}).catch(()=>{}).finally(()=>{e||g(!1)}),()=>{e=!0}},[]);let C=(0,A.useCallback)(async()=>{let e=i.trim();b(`saving`);try{let n=await f.updateConfig({llamaCppBaseUrl:e===``?null:e});if(!v.current)return;t(n),x()}catch{b(`idle`)}},[i,t,x,b]),w=(0,A.useCallback)(async e=>{b(`saving`);try{let n=await f.updateConfig({llamaCppBackendOverride:e===`auto`?null:e});if(!v.current)return;t(n),x()}catch{b(`idle`)}},[t,x,b]),ee=(0,A.useCallback)(async e=>{b(`saving`);try{let t=await f.updateLlamaCppContextSizing(e);if(!v.current)return;m(t.policy),x()}catch{b(`idle`)}},[x,b]),T=(0,A.useCallback)(async()=>{let e=o.trim();b(`saving`);try{let n=await f.updateConfig({llamaCppModelPath:e===``?null:e});if(!v.current)return;t(n),x()}catch{b(`idle`)}},[o,t,x,b]),te=(0,A.useCallback)(async e=>{b(`saving`);try{let n=await f.updateConfig({llamaCppKvCacheType:e===`q8_0`?null:e});if(!v.current)return;t(n),x()}catch{b(`idle`)}},[t,x,b]),ne=(0,A.useCallback)(async e=>{b(`saving`);try{let n=await f.updateConfig({llamaCppFlashAttn:e===`auto`?null:e});if(!v.current)return;t(n),x()}catch{b(`idle`)}},[t,x,b]),E=(0,A.useCallback)(async e=>{b(`saving`);try{let n=await f.updateConfig({llamaCppCpuMoe:e===`auto`?null:e===`on`});if(!v.current)return;t(n),x()}catch{b(`idle`)}},[t,x,b]),re=(0,A.useCallback)(async e=>{b(`saving`);try{let n=await f.updateConfig({llamaCppSwaFull:e===`auto`?null:e===`on`});if(!v.current)return;t(n),x()}catch{b(`idle`)}},[t,x,b]),ie=(0,A.useCallback)(async e=>{b(`saving`);try{let n=await f.updateConfig({llamaCppSpecType:e===`none`?null:e});if(!v.current)return;t(n),x()}catch{b(`idle`)}},[t,x,b]),ae=(0,A.useCallback)(async n=>{b(`saving`);try{let r=await f.updateConfig({defaultModel:{...e?.defaultModel,"llama-cpp":n??void 0}});if(!v.current)return;t(r),x()}catch{b(`idle`)}},[e?.defaultModel,t,x,b]),M=e?.defaultModel?.[`llama-cpp`],N=!!e?.llamaCppBaseUrl;return(0,j.jsxs)(`div`,{children:[(0,j.jsxs)(`section`,{style:{marginBottom:`2rem`},children:[(0,j.jsx)(`h3`,{children:r??D(`llama-cpp`,n?.platform)}),(0,j.jsx)(`p`,{className:`muted`,style:{marginTop:0},children:`Run AI models directly on this device using the llama.cpp engine, making the best use of the hardware you already have. Your conversations stay on your computer — no account to set up, no data sent to the cloud.`}),(0,j.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.75rem`,alignItems:`center`},children:[(0,j.jsx)(`span`,{className:`muted small`,children:`Status:`}),(0,j.jsx)(`span`,{className:`gz-status-pill gz-status-pill--ok`,children:`ready`}),N&&(0,j.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,title:`Using an external engine at: ${e?.llamaCppBaseUrl}`,children:`using external engine`}),u===`saved`&&(0,j.jsx)(`span`,{className:`muted small`,children:`saved ✓`})]})]}),c.length>1&&(0,j.jsxs)(`section`,{style:{marginBottom:`2rem`},children:[(0,j.jsx)(`h4`,{children:`Default model`}),(0,j.jsx)(`p`,{className:`muted small`,style:{marginTop:0},children:`Which local model new chat sessions use when a gezel doesn't pin one.`}),(0,j.jsx)(`div`,{className:`new-row`,style:{marginTop:`0.5rem`},children:(0,j.jsxs)(`select`,{value:M??``,onChange:e=>void ae(e.target.value||void 0),children:[(0,j.jsx)(`option`,{value:``,children:`First local model`}),c.map(e=>(0,j.jsxs)(`option`,{value:e.id,children:[e.name,` (`,e.id,`)`]},e.id))]})})]}),(0,j.jsxs)(`section`,{style:{marginBottom:`2rem`},children:[(0,j.jsx)(`h4`,{children:`Models`}),(0,j.jsx)(I,{onModelsChanged:S},p)]}),(0,j.jsx)(k,{provider:`llama-cpp`}),(0,j.jsxs)(`section`,{style:{marginBottom:`2rem`},children:[(0,j.jsx)(`h4`,{style:{marginBottom:`0.5rem`},children:`Concurrent replicas`}),(0,j.jsx)(`p`,{className:`muted small`,style:{marginTop:0},children:`Run multiple copies of the same model so unrelated sessions don't queue behind each other. Weights are shared by the OS via mmap so disk cost stays at one model file; resident memory grows because each clone keeps its own KV cache and activations.`}),(0,j.jsx)(O,{provider:`llama-cpp`,modelId:e?.defaultModel?.[`llama-cpp`]??null,config:e,onConfigChanged:t})]}),(0,j.jsx)(H,{config:e,onConfigChanged:t,platform:window.__GEZEL__?.platform??n?.platform}),(0,j.jsxs)(`details`,{className:`llama-advanced-settings`,children:[(0,j.jsxs)(`summary`,{className:`llama-advanced-summary`,children:[(0,j.jsx)(`span`,{className:`llama-advanced-caret`,"aria-hidden":`true`,children:`›`}),(0,j.jsx)(`h4`,{children:`Advanced`})]}),(0,j.jsx)(`p`,{className:`muted small`,style:{marginTop:`0.75rem`},children:`Tune how the managed on-device engine starts, or override how Gezel connects to it. Most users don't need any of these — the supervised engine handles everything. Set them only when you need a different context policy, are running your own engine process, point at a weights file that isn't in the catalog, or downgrade the accelerator.`}),(0,j.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.75rem`,alignItems:`center`},children:[(0,j.jsx)(`label`,{htmlFor:`llama-cpp-context-sizing`,className:`muted`,style:{fontSize:`0.9rem`,minWidth:`10rem`},children:`Context sizing`}),(0,j.jsxs)(`select`,{id:`llama-cpp-context-sizing`,value:p,disabled:h||u===`saving`||N,onChange:e=>void ee(e.target.value),style:{flex:1,maxWidth:`20rem`},children:[(0,j.jsx)(`option`,{value:`adaptive`,children:`Adaptive (recommended)`}),(0,j.jsx)(`option`,{value:`model-max`,children:`Model maximum (strict)`})]})]}),(0,j.jsxs)(`p`,{className:`muted small`,style:{marginTop:`0.25rem`,marginLeft:`10rem`},children:[(0,j.jsx)(`em`,{children:`Adaptive`}),` starts from model tuning (64K by default), reduces concurrency before it shortens a larger tuned window, and grows the window toward the model's maximum when fast memory has room to spare — consolidating down to two concurrent chats when that buys a meaningfully longer window, never fewer. Each model can also be pinned to a specific size from its row in the list below. `,(0,j.jsx)(`em`,{children:`Model maximum`}),` requests the model's full advertised window; if one engine slot cannot hold it safely, the model will not start. This is a machine-wide managed-engine setting. Changing it restarts idle local engines right away; a model that is mid-conversation finishes its current turn first.`,N?` External engine URLs manage their own context size.`:``]}),(0,j.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.75rem`,alignItems:`center`},children:[(0,j.jsx)(`label`,{htmlFor:`llama-cpp-engine-backend`,className:`muted`,style:{fontSize:`0.9rem`,minWidth:`10rem`},children:`Engine backend`}),(0,j.jsxs)(`select`,{id:`llama-cpp-engine-backend`,value:e?.llamaCppBackendOverride??`auto`,onChange:e=>void w(e.target.value),style:{flex:1,maxWidth:`20rem`},children:[(0,j.jsxs)(`option`,{value:`auto`,children:[`Auto-detect`,n?.llamaCppDetectedBackend?` (machine supports: ${n.llamaCppDetectedBackend}${K(n.llamaCppDetectedVendor)})`:``]}),W(n?.platform,n?.llamaCppDetectedBackend).map(e=>(0,j.jsx)(`option`,{value:e,children:G(e)},e))]}),(0,j.jsx)(`span`,{className:`muted`,style:{fontSize:`0.85rem`},children:q(e,n)?`Restart the app to apply`:``})]}),(0,j.jsxs)(`p`,{className:`muted small`,style:{marginTop:`0.25rem`,marginLeft:`10rem`},children:[`Auto-detect picks the fastest backend your machine supports; the other options are downgrades you can pin if the faster path is misbehaving. Switching `,(0,j.jsx)(`em`,{children:`back`}),` to Auto-detect from a pinned override also requires a restart.`]}),(0,j.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.75rem`,alignItems:`center`},children:[(0,j.jsx)(`label`,{className:`muted`,style:{fontSize:`0.9rem`,minWidth:`10rem`},children:`KV cache quantization`}),(0,j.jsxs)(`select`,{value:e?.llamaCppKvCacheType??`q8_0`,onChange:e=>void te(e.target.value),style:{flex:1,maxWidth:`20rem`},children:[(0,j.jsx)(`option`,{value:`f16`,children:`f16 — full precision (most memory)`}),(0,j.jsx)(`option`,{value:`q8_0`,children:`q8_0 — balanced (default)`}),(0,j.jsx)(`option`,{value:`q4_0`,children:`q4_0 — smallest (most savings)`})]})]}),(0,j.jsxs)(`p`,{className:`muted small`,style:{marginTop:`0.25rem`,marginLeft:`10rem`},children:[`Sets `,(0,j.jsx)(`code`,{children:`--cache-type-k`}),` / `,(0,j.jsx)(`code`,{children:`--cache-type-v`}),` for llama-server. Quantizing the KV cache frees RAM for longer contexts and more concurrent sessions: q8_0 is near-lossless at ~50% savings vs. f16, while q4_0 saves the most but can dent quality on attention-sensitive models. Takes effect the next time the engine starts — restart the app to apply now.`]}),(0,j.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.75rem`,alignItems:`center`},children:[(0,j.jsx)(`label`,{className:`muted`,style:{fontSize:`0.9rem`,minWidth:`10rem`},children:`Flash attention`}),(0,j.jsxs)(`select`,{value:typeof e?.llamaCppFlashAttn==`string`?e.llamaCppFlashAttn:e?.llamaCppFlashAttn===!0?`on`:`auto`,onChange:e=>void ne(e.target.value),style:{flex:1,maxWidth:`20rem`},children:[(0,j.jsx)(`option`,{value:`auto`,children:`Auto (recommended)`}),(0,j.jsx)(`option`,{value:`on`,children:`On`}),(0,j.jsx)(`option`,{value:`off`,children:`Off`})]})]}),(0,j.jsx)(`p`,{className:`muted small`,style:{marginTop:`0.25rem`,marginLeft:`10rem`},children:`Faster attention on modern GPUs, and effectively required for the fast path under a quantized KV cache (the default). Auto lets llama-server decide; the engine forces it on when the KV cache is quantized. Takes effect the next time the engine starts.`}),(0,j.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.75rem`,alignItems:`center`},children:[(0,j.jsx)(`label`,{className:`muted`,style:{fontSize:`0.9rem`,minWidth:`10rem`},children:`Speculative decoding`}),(0,j.jsxs)(`select`,{value:e?.llamaCppSpecType??`none`,onChange:e=>void ie(e.target.value),style:{flex:1,maxWidth:`20rem`},children:[(0,j.jsx)(`option`,{value:`none`,children:`Off`}),(0,j.jsx)(`option`,{value:`ngram-mod`,children:`N-gram lookup (no draft model)`}),(0,j.jsx)(`option`,{value:`draft-mtp`,children:`Model MTP head (experimental)`})]})]}),(0,j.jsxs)(`p`,{className:`muted small`,style:{marginTop:`0.25rem`,marginLeft:`10rem`},children:[`Drafts several tokens per step and verifies them against the target model. `,(0,j.jsx)(`em`,{children:`N-gram`}),` `,`needs no extra model and helps most on repetitive or structured output. `,(0,j.jsx)(`em`,{children:`MTP`}),` uses the model's own prediction head, requires compatible downloaded weights, and may change behavior on experimental engine/model combinations. Takes effect the next time the engine starts.`]}),(0,j.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.75rem`,alignItems:`center`},children:[(0,j.jsx)(`label`,{className:`muted`,style:{fontSize:`0.9rem`,minWidth:`10rem`},children:`MoE expert offload`}),(0,j.jsxs)(`select`,{value:U(e?.llamaCppCpuMoe),onChange:e=>void E(e.target.value),style:{flex:1,maxWidth:`20rem`},children:[(0,j.jsx)(`option`,{value:`auto`,children:`Auto — detect when offload is needed (default)`}),(0,j.jsx)(`option`,{value:`on`,children:`On — always offload experts (--cpu-moe)`}),(0,j.jsx)(`option`,{value:`off`,children:`Off — keep experts on the GPU`})]})]}),(0,j.jsxs)(`p`,{className:`muted small`,style:{marginTop:`0.25rem`,marginLeft:`10rem`},children:[`For big Mixture-of-Experts models on a small GPU: run attention on the GPU while streaming the sparse expert weights from system RAM — lets a model that wouldn't fit in VRAM run anyway. `,(0,j.jsx)(`em`,{children:`Auto`}),` turns this on only for a MoE model that won't fit in VRAM (and sizes a partial split when it can), and leaves dense models and UMA machines alone. Takes effect the next time the engine starts.`]}),(0,j.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.75rem`,alignItems:`center`},children:[(0,j.jsx)(`label`,{className:`muted`,style:{fontSize:`0.9rem`,minWidth:`10rem`},children:`Full SWA cache`}),(0,j.jsxs)(`select`,{value:U(e?.llamaCppSwaFull),onChange:e=>void re(e.target.value),style:{flex:1,maxWidth:`20rem`},children:[(0,j.jsx)(`option`,{value:`auto`,children:`Auto — full only when it fits fast memory`}),(0,j.jsx)(`option`,{value:`on`,children:`On — always full cache (--swa-full)`}),(0,j.jsx)(`option`,{value:`off`,children:`Off — memory-efficient windowed cache`})]})]}),(0,j.jsxs)(`p`,{className:`muted small`,style:{marginTop:`0.25rem`,marginLeft:`10rem`},children:[`For sliding-window models (the Gemma family): retain old KV entries that the memory-efficient windowed cache normally discards. This can enable prompt reuse and other cache operations where the engine supports them, but its memory cost grows with context.`,` `,(0,j.jsx)(`em`,{children:`Auto`}),` uses the full cache only when the model weights and full KV cache fit in fast memory — VRAM on a discrete GPU — and otherwise keeps the windowed cache. Takes effect the next time the engine starts.`]}),(0,j.jsxs)(`p`,{className:`muted small`,style:{marginTop:`0.5rem`,marginLeft:`10rem`},children:[`More engine flags (an explicit GPU-layer count, partial expert split, prompt-reuse size, threads, and a raw-flag escape hatch) live in `,(0,j.jsx)(`code`,{children:`config.json`}),` under the`,` `,(0,j.jsx)(`code`,{children:`llamaCpp*`}),` keys.`]}),(0,j.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.75rem`,alignItems:`center`},children:[(0,j.jsx)(`label`,{className:`muted`,style:{fontSize:`0.9rem`,minWidth:`10rem`},children:`External engine URL`}),(0,j.jsx)(`input`,{type:`text`,placeholder:`e.g. http://127.0.0.1:8080 (leave blank to use the supervised engine)`,value:i,onChange:e=>a(e.target.value),style:{flex:1}}),(0,j.jsx)(`button`,{type:`button`,disabled:u===`saving`||i===(e?.llamaCppBaseUrl??``),onClick:()=>void C(),children:`Save`})]}),(0,j.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.5rem`,alignItems:`center`},children:[(0,j.jsx)(`label`,{className:`muted`,style:{fontSize:`0.9rem`,minWidth:`10rem`},children:`Override model path`}),(0,j.jsx)(`input`,{type:`text`,placeholder:`Absolute path to a .gguf file (overrides the local-models default)`,value:o,onChange:e=>s(e.target.value),style:{flex:1}}),(0,j.jsx)(`button`,{type:`button`,disabled:u===`saving`||o===(e?.llamaCppModelPath??``),onClick:()=>void T(),children:`Save`})]}),(0,j.jsx)(fe,{})]})]})}function fe(){let[e,t]=(0,A.useState)({kind:`idle`}),n=(0,A.useCallback)(async()=>{t({kind:`loading`});try{let e=await f.getLlamaCppLog(4096);t({kind:`loaded`,path:e.path,tail:e.tail})}catch(e){t({kind:`error`,message:e instanceof Error?e.message:String(e)})}},[]);return(0,j.jsxs)(`details`,{style:{marginTop:`1rem`},children:[(0,j.jsxs)(`summary`,{style:{cursor:`pointer`,userSelect:`none`},children:[`Engine log`,` `,(0,j.jsx)(`span`,{className:`muted small`,children:`— technical output from llama-server. Useful for bug reports.`})]}),(0,j.jsxs)(`div`,{style:{marginTop:`0.5rem`},children:[(0,j.jsxs)(`div`,{className:`new-row`,style:{alignItems:`center`,gap:`0.5rem`},children:[(0,j.jsx)(`button`,{type:`button`,onClick:()=>void n(),disabled:e.kind===`loading`,children:e.kind===`loading`?`Loading…`:`Refresh`}),e.kind===`loaded`&&e.path&&(0,j.jsx)(`span`,{className:`muted small`,title:e.path,children:e.path}),e.kind===`loaded`&&!e.path&&(0,j.jsx)(`span`,{className:`muted small`,children:`No supervised engine running.`})]}),e.kind===`error`&&(0,j.jsxs)(`div`,{className:`muted small`,style:{marginTop:`0.5rem`,color:`#ff9b9b`},children:[`Couldn't load log: `,e.message]}),e.kind===`loaded`&&e.tail&&(0,j.jsx)(`pre`,{style:{marginTop:`0.5rem`,padding:`0.5rem`,background:`rgba(255,255,255,0.04)`,border:`1px solid rgba(255,255,255,0.1)`,borderRadius:4,maxHeight:`18rem`,overflow:`auto`,fontSize:`0.75rem`,fontFamily:`ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace`,whiteSpace:`pre-wrap`,wordBreak:`break-all`},children:e.tail}),e.kind===`loaded`&&!e.tail&&e.path&&(0,j.jsx)(`div`,{className:`muted small`,style:{marginTop:`0.5rem`},children:`Log is empty. (Engine may not have started yet — try chatting with an on-device gezel first.)`})]})]})}export{J as LlamaCppSettings};
@@ -1 +1 @@
1
- import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{n as t,t as n}from"./jsx-runtime-CEpd2cAX.js";import{n as r}from"./styles-CKr_yrbn.js";import{ft as i}from"./index-DXWR4qW1.js";var a=e(t(),1),o=n();function s({value:e,readOnly:t,placeholder:n,minHeight:s=`80px`,maxHeight:c=`40vh`,onCommit:l}){let u=i(),d=(0,a.useRef)(e),f=(0,a.useRef)(e),p=(0,a.useCallback)(e=>{d.current=e},[]),m=(0,a.useCallback)(()=>{t||d.current!==f.current&&(f.current=d.current,l(d.current))},[t,l]),h=(0,a.useCallback)(e=>{e.currentTarget.contains(e.relatedTarget)||m()},[m]),g=(0,a.useRef)(m);return g.current=m,(0,a.useEffect)(()=>()=>g.current(),[]),(0,o.jsx)(`div`,{className:`markdown-field`,onBlur:h,children:(0,o.jsx)(r,{initialMarkdown:e,initialView:`wysiwyg`,onChange:p,readOnly:t??!1,colorScheme:u,uxFont:`var(--font-ui)`,...n?{placeholder:n}:{},minHeight:s,maxHeight:c,showPlayTab:!1,showStatusBar:!1,showFilesToggle:!1,fullWidth:!0,thinMargins:!0})})}export{s as t};
1
+ import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{n as t,t as n}from"./jsx-runtime-CEpd2cAX.js";import{n as r}from"./styles-CKVKwqoQ.js";import{ht as i}from"./index-C0DYtvfg.js";var a=e(t(),1),o=n();function s({value:e,readOnly:t,placeholder:n,minHeight:s=`80px`,maxHeight:c=`40vh`,onCommit:l}){let u=i(),d=(0,a.useRef)(e),f=(0,a.useRef)(e),p=(0,a.useCallback)(e=>{d.current=e},[]),m=(0,a.useCallback)(()=>{t||d.current!==f.current&&(f.current=d.current,l(d.current))},[t,l]),h=(0,a.useCallback)(e=>{e.currentTarget.contains(e.relatedTarget)||m()},[m]),g=(0,a.useRef)(m);return g.current=m,(0,a.useEffect)(()=>()=>g.current(),[]),(0,o.jsx)(`div`,{className:`markdown-field`,onBlur:h,children:(0,o.jsx)(r,{initialMarkdown:e,initialView:`wysiwyg`,onChange:p,readOnly:t??!1,colorScheme:u,uxFont:`var(--font-ui)`,...n?{placeholder:n}:{},minHeight:s,maxHeight:c,showPlayTab:!1,showStatusBar:!1,showFilesToggle:!1,fullWidth:!0,thinMargins:!0})})}export{s as t};
@@ -0,0 +1 @@
1
+ import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{n as t,t as n}from"./jsx-runtime-CEpd2cAX.js";import{t as r}from"./api-BPraLwsh.js";import{x as i}from"./index-C0DYtvfg.js";import{c as a}from"./SquisqIntegration-6v3yNOIP.js";var o=e(t(),1),s=n();function c({gezelId:e,gezelName:t}){let[n,i]=(0,o.useState)(null),[a,c]=(0,o.useState)(null),[u,f]=(0,o.useState)({loading:!1,content:null,error:null});(0,o.useEffect)(()=>{let t=!1;return i(null),c(null),(async()=>{let[n,a,o]=await Promise.all([r.listMemoryDays(`gezel`,e).then(e=>e.days).catch(()=>[]),r.readMemorySummary(`gezel`,e).then(e=>e.content).catch(()=>``),r.readMemoryLessons(e).then(e=>e.content).catch(()=>``)]);t||i({days:n,summary:a||null,lessons:o||null,expanded:!0})})(),()=>{t=!0}},[e]),(0,o.useEffect)(()=>{if(!a){f({loading:!1,content:null,error:null});return}let t=!1;return f({loading:!0,content:null,error:null}),(async()=>{try{let n=a.kind===`summary`?await r.readMemorySummary(`gezel`,e):a.kind===`lessons`?await r.readMemoryLessons(e):await r.readMemoryDay(`gezel`,e,a.day);t||f({loading:!1,content:n.content,error:null})}catch(e){t||f({loading:!1,content:null,error:e instanceof Error?e.message:String(e)})}})(),()=>{t=!0}},[e,a]);let p=(0,o.useCallback)(()=>{i(e=>e&&{...e,expanded:!e.expanded})},[]);return n===null?(0,s.jsx)(`p`,{className:`muted small`,children:`Loading memories…`}):n.days.length===0&&!n.summary&&!n.lessons?(0,s.jsx)(`p`,{className:`placeholder`,children:`No memories yet. This gezel will build an individual memory over time as you work together.`}):(0,s.jsxs)(`div`,{className:`memories-pane`,"data-testid":`memories-tree`,children:[(0,s.jsxs)(`div`,{className:`memories-tree`,role:`tree`,children:[(0,s.jsxs)(`p`,{className:`memories-tree-total muted small`,children:[n.days.length,` day`,n.days.length===1?``:`s`,` of individual memories.`]}),(0,s.jsx)(l,{gezelName:t,tree:n,onToggle:p,onSelect:c,selected:a})]}),(0,s.jsx)(d,{selected:a,preview:u})]})}function l({gezelName:e,tree:t,onToggle:n,onSelect:r,selected:i}){return(0,s.jsxs)(`div`,{className:`memories-tree-scope`,role:`treeitem`,"aria-expanded":t.expanded,children:[(0,s.jsxs)(`button`,{type:`button`,className:`memories-tree-scope-header`,onClick:n,children:[(0,s.jsx)(`span`,{className:`memories-tree-caret`,"aria-hidden":!0,children:t.expanded?`▾`:`▸`}),(0,s.jsx)(`span`,{className:`memories-tree-scope-label`,children:e}),(0,s.jsxs)(`span`,{className:`muted small`,children:[t.days.length,` day`,t.days.length===1?``:`s`,t.lessons?` + lessons`:``,t.summary?` + summary`:``]})]}),t.expanded&&(0,s.jsxs)(`ul`,{className:`memories-tree-children`,children:[t.lessons&&(0,s.jsx)(u,{active:i?.kind===`lessons`,label:`lessons`,onClick:()=>r({kind:`lessons`,label:`${e} · lessons`})}),t.summary&&(0,s.jsx)(u,{active:i?.kind===`summary`,label:`summary`,onClick:()=>r({kind:`summary`,label:`${e} · summary`})}),t.days.map(t=>(0,s.jsx)(u,{active:i?.kind===`day`&&i.day===t,label:t,onClick:()=>r({kind:`day`,day:t,label:`${e} · ${t}`})},t))]})]})}function u({active:e,label:t,onClick:n}){return(0,s.jsx)(`li`,{children:(0,s.jsx)(`button`,{type:`button`,className:`memories-tree-leaf${e?` memories-tree-leaf-active`:``}`,onClick:n,children:t})})}function d({selected:e,preview:t}){return(0,s.jsx)(`div`,{className:`memories-preview`,children:e?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(`header`,{className:`memories-preview-header`,children:(0,s.jsx)(`code`,{children:e.label})}),t.loading&&(0,s.jsx)(`p`,{className:`muted small`,children:`Loading…`}),t.error&&(0,s.jsx)(`p`,{className:`error`,children:t.error}),t.content!==null&&!t.loading&&!t.error&&(0,s.jsx)(`pre`,{className:`memories-preview-body`,children:t.content||`(empty)`})]}):(0,s.jsx)(`p`,{className:`placeholder`,children:`Select a day or lesson on the left to view its contents.`})})}function f({projectId:e,projectName:t}){let[n,i]=(0,o.useState)(null),[a,c]=(0,o.useState)(null),[l,d]=(0,o.useState)(null),[f,m]=(0,o.useState)(null);return(0,o.useEffect)(()=>{let t=!1;return i(null),c(null),d(null),m(null),r.listMemoryDays(`project`,e).then(e=>{t||(i(e.days),d(e.days[0]??null))}).catch(e=>{t||(i([]),c(e instanceof Error?e.message:String(e)))}),()=>{t=!0}},[e]),(0,o.useEffect)(()=>{if(!l){m(null);return}let t=!1,n=l;return m({day:n,loading:!0,content:null,error:null}),r.readMemoryDay(`project`,e,n).then(e=>{t||m({day:n,loading:!1,content:e.content,error:null})}).catch(e=>{t||m({day:n,loading:!1,content:null,error:e instanceof Error?e.message:String(e)})}),()=>{t=!0}},[e,l]),(0,s.jsxs)(`section`,{id:`project-about-memories`,className:`project-about-section project-about-anchor`,children:[(0,s.jsx)(`h3`,{className:`project-about-section-title`,children:`Project memories`}),(0,s.jsx)(`p`,{className:`muted small project-memories-hint`,children:`Notes shared by every gezel working in this project. Changes are saved to the project’s memory files and used in future recall.`}),n===null?(0,s.jsx)(`p`,{className:`muted small`,children:`Loading memories…`}):a?(0,s.jsx)(`p`,{className:`error`,children:a}):n.length===0?(0,s.jsx)(`p`,{className:`placeholder`,children:`No project memories yet. Gezels add shared notes here as work progresses.`}):(0,s.jsxs)(`div`,{className:`project-memories-browser`,children:[(0,s.jsxs)(`div`,{className:`memories-tree project-memories-days`,children:[(0,s.jsxs)(`p`,{className:`memories-tree-total muted small`,children:[n.length,` day`,n.length===1?``:`s`]}),(0,s.jsx)(`ul`,{className:`memories-tree-children project-memories-day-list`,children:n.map(e=>(0,s.jsx)(u,{active:l===e,label:e,onClick:()=>d(e)},e))})]}),(0,s.jsxs)(`div`,{className:`project-memory-editor`,children:[f?.loading&&(0,s.jsx)(`p`,{className:`muted small`,children:`Loading…`}),f?.error&&(0,s.jsx)(`p`,{className:`error`,children:f.error}),f?.content!==null&&f&&!f.loading&&!f.error&&(0,s.jsx)(p,{projectId:e,projectName:t,day:f.day,initial:f.content},`${e}:${f.day}`)]})]})]})}function p({projectId:e,projectName:t,day:n,initial:o}){let c=i({resourceKey:`project:${e}:memory:${n}`,initialValue:o,save:t=>r.updateMemoryDay(`project`,e,n,t)});return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(`div`,{className:`project-memory-editor-heading`,children:(0,s.jsxs)(`code`,{children:[t,` · `,n]})}),(0,s.jsxs)(`div`,{className:`project-memory-source-editor`,children:[(0,s.jsx)(`textarea`,{className:`project-memory-source`,"aria-label":`${t} memory for ${n}`,value:c.desiredValue(),onChange:e=>c.update(e.target.value),spellCheck:!1}),(0,s.jsxs)(`div`,{className:`project-memory-source-status`,children:[(0,s.jsx)(`span`,{children:`Memory markdown`}),(0,s.jsx)(a,{autosave:c})]})]})]})}export{f as n,c as t};
@@ -1 +1 @@
1
- import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{n as t,t as n}from"./jsx-runtime-CEpd2cAX.js";import{t as r}from"./api-BX5xXiFs.js";import{n as i,t as a}from"./microphone-input-5gqW_NKf.js";var o=e(t(),1),s=n();function c(){let[e,t]=(0,o.useState)([]),[n,i]=(0,o.useState)(``),[c,d]=(0,o.useState)(``),[f,p]=(0,o.useState)(!1),[m,h]=(0,o.useState)(null);(0,o.useEffect)(()=>{r.getConfig().then(e=>{i(e.microphoneDeviceId??``),d(e.microphoneDeviceLabel??``)}).catch(e=>h(u(e)))},[]);let g=(0,o.useCallback)(async(e=!1)=>{if(!navigator.mediaDevices?.enumerateDevices){h(`Microphone selection is unavailable in this browser.`);return}let n;try{e&&(n=await navigator.mediaDevices.getUserMedia({audio:!0,video:!1})),t(await a()),h(null)}catch(e){h(u(e))}finally{for(let e of n?.getTracks()??[])e.stop()}},[]);(0,o.useEffect)(()=>{g();let e=navigator.mediaDevices;if(!e?.addEventListener)return;let t=()=>void g();return e.addEventListener(`devicechange`,t),()=>e.removeEventListener(`devicechange`,t)},[g]);let _=(0,o.useCallback)(async t=>{let a=n,o=c,s=e.find(e=>e.deviceId===t)?.label??``;i(t),d(s),p(!0);try{let e=await r.updateConfig({microphoneDeviceId:t||null,microphoneDeviceLabel:s||null});i(e.microphoneDeviceId??``),d(e.microphoneDeviceLabel??``),window.dispatchEvent(new CustomEvent(`gezel:config-updated`,{detail:e})),h(null)}catch(e){i(a),d(o),h(u(e))}finally{p(!1)}},[n,c,e]),v=e.length===0||e.every(e=>!e.label);return(0,s.jsxs)(`section`,{style:{marginTop:`2rem`},children:[(0,s.jsx)(`h3`,{children:`Microphone`}),(0,s.jsx)(`p`,{className:`muted`,style:{marginTop:0},children:`Choose the input used by the Narrate button in chat.`}),(0,s.jsxs)(`div`,{style:{display:`flex`,gap:`0.5rem`,alignItems:`center`,flexWrap:`wrap`},children:[(0,s.jsxs)(`label`,{className:`provider-row`,children:[(0,s.jsx)(`span`,{children:`Input`}),(0,s.jsxs)(`select`,{"aria-label":`Microphone input`,value:l(e,n,c),disabled:f,onChange:e=>void _(e.target.value),children:[(0,s.jsx)(`option`,{value:``,children:`System default`}),e.map((e,t)=>(0,s.jsx)(`option`,{value:e.deviceId,children:e.label||`Microphone ${t+1}`},e.deviceId)),n&&!e.some(e=>e.deviceId===n)&&!e.some(e=>c&&e.label===c)&&(0,s.jsxs)(`option`,{value:n,children:[c||`Saved microphone`,` (not currently available)`]})]})]}),(0,s.jsx)(`button`,{type:`button`,onClick:()=>void g(v),children:v?`Identify microphones`:`Refresh`})]}),(0,s.jsx)(`p`,{className:`muted small`,children:`Choose System default to follow your operating system's input selection.`}),m&&(0,s.jsx)(`p`,{className:`error`,children:m})]})}function l(e,t,n){return i(e,{...t?{deviceId:t}:{},...n?{label:n}:{}})?.deviceId??t}function u(e){return e instanceof Error?e.message:String(e)}export{c as MicrophoneSettings};
1
+ import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{n as t,t as n}from"./jsx-runtime-CEpd2cAX.js";import{t as r}from"./api-BPraLwsh.js";import{n as i,t as a}from"./microphone-input-5gqW_NKf.js";var o=e(t(),1),s=n();function c(){let[e,t]=(0,o.useState)([]),[n,i]=(0,o.useState)(``),[c,d]=(0,o.useState)(``),[f,p]=(0,o.useState)(!1),[m,h]=(0,o.useState)(null);(0,o.useEffect)(()=>{r.getConfig().then(e=>{i(e.microphoneDeviceId??``),d(e.microphoneDeviceLabel??``)}).catch(e=>h(u(e)))},[]);let g=(0,o.useCallback)(async(e=!1)=>{if(!navigator.mediaDevices?.enumerateDevices){h(`Microphone selection is unavailable in this browser.`);return}let n;try{e&&(n=await navigator.mediaDevices.getUserMedia({audio:!0,video:!1})),t(await a()),h(null)}catch(e){h(u(e))}finally{for(let e of n?.getTracks()??[])e.stop()}},[]);(0,o.useEffect)(()=>{g();let e=navigator.mediaDevices;if(!e?.addEventListener)return;let t=()=>void g();return e.addEventListener(`devicechange`,t),()=>e.removeEventListener(`devicechange`,t)},[g]);let _=(0,o.useCallback)(async t=>{let a=n,o=c,s=e.find(e=>e.deviceId===t)?.label??``;i(t),d(s),p(!0);try{let e=await r.updateConfig({microphoneDeviceId:t||null,microphoneDeviceLabel:s||null});i(e.microphoneDeviceId??``),d(e.microphoneDeviceLabel??``),window.dispatchEvent(new CustomEvent(`gezel:config-updated`,{detail:e})),h(null)}catch(e){i(a),d(o),h(u(e))}finally{p(!1)}},[n,c,e]),v=e.length===0||e.every(e=>!e.label);return(0,s.jsxs)(`section`,{style:{marginTop:`2rem`},children:[(0,s.jsx)(`h3`,{children:`Microphone`}),(0,s.jsx)(`p`,{className:`muted`,style:{marginTop:0},children:`Choose the input used by the Narrate button in chat.`}),(0,s.jsxs)(`div`,{style:{display:`flex`,gap:`0.5rem`,alignItems:`center`,flexWrap:`wrap`},children:[(0,s.jsxs)(`label`,{className:`provider-row`,children:[(0,s.jsx)(`span`,{children:`Input`}),(0,s.jsxs)(`select`,{"aria-label":`Microphone input`,value:l(e,n,c),disabled:f,onChange:e=>void _(e.target.value),children:[(0,s.jsx)(`option`,{value:``,children:`System default`}),e.map((e,t)=>(0,s.jsx)(`option`,{value:e.deviceId,children:e.label||`Microphone ${t+1}`},e.deviceId)),n&&!e.some(e=>e.deviceId===n)&&!e.some(e=>c&&e.label===c)&&(0,s.jsxs)(`option`,{value:n,children:[c||`Saved microphone`,` (not currently available)`]})]})]}),(0,s.jsx)(`button`,{type:`button`,onClick:()=>void g(v),children:v?`Identify microphones`:`Refresh`})]}),(0,s.jsx)(`p`,{className:`muted small`,children:`Choose System default to follow your operating system's input selection.`}),m&&(0,s.jsx)(`p`,{className:`error`,children:m})]})}function l(e,t,n){return i(e,{...t?{deviceId:t}:{},...n?{label:n}:{}})?.deviceId??t}function u(e){return e instanceof Error?e.message:String(e)}export{c as MicrophoneSettings};
@@ -0,0 +1 @@
1
+ import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{n as t,t as n}from"./jsx-runtime-CEpd2cAX.js";import{A as r,Jt as i,_t as a}from"./dist-BqGwkOe5.js";import{t as o}from"./api-BPraLwsh.js";import{t as s}from"./model-context-DBqdK0PS.js";import{r as c}from"./model-memory-copy-CeuXAj-T.js";import{t as l}from"./ConfirmDialog-Dt1ed4Fh.js";import{a as u,r as d,t as f}from"./model-inventory-ykSm_IT5.js";import{Pt as p,wt as m}from"./index-C0DYtvfg.js";import{t as h}from"./CatalogBrowser-DEM9t7Es.js";import{n as g,r as _,t as v}from"./InstallProgressRow-DyKOI4MU.js";import{t as y}from"./IncompleteDownloads-BiPaaahS.js";import{t as b}from"./LicenseButton-D3VmcVG1.js";import{a as x,i as S,n as C,o as w,r as T,t as E}from"./UnrecognizedModels-HtdMZUqK.js";import{n as D,r as O,t as ee}from"./model-quantization-CLO7XLoF.js";var k=e(t(),1),A=n(),j=5e3,M=1024*1024,N=512,P=32*1024,F=4*1024,I=256;function L(e){if(e<1024)return`${Math.round(e)} MB`;let t=e/1024;return`${Number.isInteger(t)?t:t.toFixed(1)} GB`}function R({providerName:e,label:t,configuredBudgetMb:n}){let[r,i]=(0,k.useState)(null),[a,s]=(0,k.useState)(n??null),[c,l]=(0,k.useState)(!1),[u,d]=(0,k.useState)(!1),[f,m]=(0,k.useState)(null),h=(0,k.useCallback)(async()=>{try{let t=(await o.getCacheStats()).providers.find(t=>t.providerName===e)??null;i(t)}catch{}},[e]);(0,k.useEffect)(()=>{h();let e=setInterval(()=>void h(),j);return()=>clearInterval(e)},[h]),(0,k.useEffect)(()=>{s(n??null)},[n]);let g=(0,k.useCallback)(async t=>{l(!0),m(null);try{await o.updateConfig({cacheBudgetMb:{[e]:t}}),m(t===void 0?`Reset to auto`:`Saved`),await h()}catch(e){m(`Failed to save: ${e instanceof Error?e.message:String(e)}`)}finally{l(!1)}},[e,h]),_=(0,k.useCallback)(async()=>{d(!0),m(null);try{await o.clearProviderCache(e),m(`Cleared all caches`),await h()}catch(e){m(`Failed to clear: ${e instanceof Error?e.message:String(e)}`)}finally{d(!1)}},[e,h]),v=r?Math.round(r.totalBytes/M):0,y=r?Math.round(r.budgetBytes/M):0,b=p(r?.sessions,r?.warmSessionCount??0),x=r?.defaultBudgetBytes?Math.round(r.defaultBudgetBytes/M):y||2048,S=Math.min(N,x),C=r?.systemRamBytes?Math.max(x,Math.round(r.systemRamBytes/M)-F):Math.max(P,x*2),w=Math.min(Math.max(a??x,S),C),T=a===null||Math.abs(a-x)<=I,E=n!==void 0,D=(a??x)!==(n??x),O=(x-S)/Math.max(1,C-S)*100;return(0,A.jsxs)(`div`,{className:`cache-controls-panel`,children:[(0,A.jsx)(`h4`,{children:`Memory budget`}),(0,A.jsxs)(`p`,{className:`muted small`,children:[`The most memory `,t,` keeps for chat and shared-prefix context before older entries are released.`]}),r&&b.totalCount>0?(0,A.jsxs)(`p`,{className:`muted small`,children:[b.label,` · `,L(v),` used of `,L(y),r.recentHitRate>0&&(0,A.jsxs)(A.Fragment,{children:[` · `,Math.round(r.recentHitRate*100),`% hit rate (last 50 turns)`]})]}):(0,A.jsx)(`p`,{className:`muted small`,children:`No warm cache entries yet — they populate after the first turn.`}),(0,A.jsxs)(`div`,{className:`gz-budget-slider`,children:[(0,A.jsxs)(`div`,{className:`gz-budget-slider-head`,children:[(0,A.jsx)(`strong`,{children:L(w)}),T?(0,A.jsx)(`span`,{className:`gz-budget-tag`,children:`Auto (RAM-aware)`}):(0,A.jsx)(`span`,{className:`gz-budget-tag gz-budget-tag-custom`,children:`Custom`})]}),(0,A.jsxs)(`div`,{className:`gz-budget-track`,children:[(0,A.jsx)(`input`,{type:`range`,min:S,max:C,step:256,value:w,"aria-label":`Memory budget for ${t}`,onChange:e=>s(Number.parseInt(e.target.value,10))}),(0,A.jsxs)(`div`,{className:`gz-budget-marker`,style:{left:`${O}%`},title:`Suggested for this Mac: ${L(x)}`,"aria-hidden":`true`,children:[(0,A.jsx)(`span`,{className:`gz-budget-marker-arrow`,children:`▲`}),(0,A.jsxs)(`span`,{className:`gz-budget-marker-label`,children:[`Auto · `,L(x)]})]})]}),(0,A.jsxs)(`div`,{className:`gz-budget-scale muted small`,children:[(0,A.jsx)(`span`,{children:L(S)}),(0,A.jsx)(`span`,{children:L(C)})]})]}),(0,A.jsxs)(`div`,{className:`cache-budget-actions`,style:{marginTop:`0.75rem`},children:[(0,A.jsx)(`button`,{type:`button`,onClick:()=>void g(T?void 0:w),disabled:c||!D,children:c?`Saving…`:`Save`}),E&&(0,A.jsx)(`button`,{type:`button`,onClick:()=>void g(void 0),disabled:c,style:{marginLeft:`0.5rem`},children:`Reset to auto`})]}),(0,A.jsx)(`div`,{style:{marginTop:`0.75rem`},children:(0,A.jsx)(`button`,{type:`button`,onClick:()=>void _(),disabled:u||!r||b.totalCount===0,children:u?`Clearing…`:`Clear all caches`})}),f&&(0,A.jsx)(`p`,{className:`muted small`,style:{marginTop:`0.5rem`},children:f})]})}function z(e){return e.residentBytes??Math.round(e.approxSizeBytes*1.3)}function te(e,t){return z(e)<=t}function ne(e){return`~${c(e)}`}function B(e){if(!e)return null;let t=new Date(e);return Number.isNaN(t.getTime())?null:t.toLocaleDateString(void 0,{year:`numeric`,month:`short`})}function V(e){return e.kind!==`chat-model`||!e.mlx||e.mlx.disabledReason?null:e}var re={"mix of experts":`Only a fraction of the model's parameters run per token, so it's faster than a dense model of the same nominal size.`,vision:`Can accept images alongside text.`,tools:`Supports function/tool calling via the API.`,multimodal:`Handles multiple input types (text + images).`,large:`Heavy model — needs a lot of memory and runs more slowly.`,small:`Compact model — runs quickly on modest hardware.`};function H({onModelsChanged:e,compact:t=!1}){let[n,c]=(0,k.useState)([]),[p,v]=(0,k.useState)(null),[D,O]=(0,k.useState)([]),[j,M]=(0,k.useState)([]),[N,P]=(0,k.useState)(new Map),[F,I]=(0,k.useState)(null),[L,R]=(0,k.useState)(null),[z,H]=(0,k.useState)(null),[W,G]=(0,k.useState)(null),[K,ae]=(0,k.useState)(null),[q,oe]=(0,k.useState)(!1),[J,se]=(0,k.useState)(`all`),[Y,ce]=(0,k.useState)(null),[le,X]=(0,k.useState)(!1),[ue,de]=(0,k.useState)([]),[fe,pe]=(0,k.useState)(new Map),[me,he]=(0,k.useState)([]),ge=(0,k.useRef)([]),Z=(0,k.useCallback)(async()=>{try{let e=await o.listModelFitness();pe(new Map(e.records.map(e=>[e.key,e]))),he(e.probing),ge.current=e.probing}catch{}},[]),_e=(0,k.useCallback)(async()=>{try{let e=await o.listIncompleteMlxModels();O(e.incomplete??[])}catch{}},[]),Q=(0,k.useCallback)(async()=>{try{let e=await o.listMlxModels();c(e.models),M(e.unrecognized??[]),v(null)}catch(e){v(e instanceof Error?e.message:String(e))}Z(),_e()},[Z,_e]);(0,k.useEffect)(()=>{Q(),o.getMemoryProfile().then(e=>ae(e)).catch(()=>{}),o.getModelContextOverrides(`mlx`).then(()=>X(!0)).catch(()=>X(!1))},[Q]),(0,k.useEffect)(()=>{let e=e=>{u(e)===`mlx`&&Q()};return window.addEventListener(f,e),()=>window.removeEventListener(f,e)},[Q]),(0,k.useEffect)(()=>{let e=!1,t=async()=>{try{let t=await o.listMlxActiveInstalls();if(e)return;P(e=>{let n=new Map(e),r=new Set;for(let e of t.installs){r.add(e.catalogId);let t=n.get(e.catalogId);t&&t.origin===`local`||n.set(e.catalogId,{catalogId:e.catalogId,fileIndex:0,fileCount:1,file:``,bytesWrittenAll:e.bytesWritten,totalBytesAll:e.totalBytes,phase:e.phase,origin:`remote`})}for(let[e,t]of n)t.origin===`remote`&&!r.has(e)&&n.delete(e);return n}),t.installs.length===0&&Q()}catch{}};t();let n=setInterval(()=>void t(),2e3);return()=>{e=!0,clearInterval(n)}},[Q]),(0,k.useEffect)(()=>{let e=!1,t,n=async()=>{await Z(),!e&&(t=setTimeout(()=>void n(),ge.current.length>0?2e3:15e3))};return n(),()=>{e=!0,t&&clearTimeout(t)}},[Z]);let ve=(0,k.useCallback)((e,t)=>{if(t.type===`progress`)P(n=>{let r=n.get(e);if(!r)return n;let i=new Map(n),{retrying:a,error:o,...s}=r;return i.set(e,{...s,fileIndex:t.fileIndex,fileCount:t.fileCount,file:t.file,bytesWrittenAll:t.bytesWrittenAll,totalBytesAll:t.totalBytesAll||r.totalBytesAll,phase:`downloading`}),i});else if(t.type===`retrying`)P(n=>{let r=n.get(e);if(!r)return n;let i=new Map(n);return i.set(e,{...r,retrying:{attempt:t.attempt,maxAttempts:t.maxAttempts,delayMs:t.delayMs,reason:t.reason,file:t.file}}),i});else if(t.type===`verifying`)P(n=>{let r=n.get(e);if(!r)return n;let i=new Map(n);return i.set(e,{...r,file:t.file,phase:`verifying`}),i});else if(t.type===`extracting-metadata`)P(t=>{let n=t.get(e);if(!n)return t;let r=new Map(t);return r.set(e,{...n,phase:`extracting-metadata`}),r});else if(t.type===`done`)t.warning&&I({id:t.id,message:t.warning});else if(t.type===`error`){if(t.mismatch){let n=t.mismatch.file;P(t=>{let n=new Map(t);return n.delete(e),n}),H({catalogId:e,file:n});return}P(n=>{let r=n.get(e);if(!r)return n;let i=new Map(n);return i.set(e,{...r,error:t.error,retrying:void 0}),i}),R(t.error)}},[]),$=(0,k.useCallback)((t,n)=>{if(N.has(t))return;R(null),H(null);let r=new AbortController;P(e=>{let n=new Map(e);return n.set(t,{catalogId:t,fileIndex:0,fileCount:1,file:``,bytesWrittenAll:0,totalBytesAll:0,phase:`downloading`,origin:`local`,controller:r}),n}),(async()=>{try{await o.installMlxModel(t,e=>ve(t,e),r.signal,n?.skipSha?{skipSha:!0}:void 0),d(`mlx`)}catch(e){if(!r.signal.aborted){let n=`download failed: ${U(e)}`;R(n),P(e=>{let r=e.get(t);if(!r)return e;let i=new Map(e);return i.set(t,{...r,error:r.error??n,retrying:void 0}),i})}}finally{P(e=>{let n=new Map(e),r=n.get(t);return r?.error?(n.set(t,{...r,controller:void 0}),n):(n.delete(t),n)}),Q(),e?.()}})()},[N,Q,ve,e]),ye=(0,k.useCallback)(e=>{H(null),$(e,{skipSha:!0})},[$]),be=(0,k.useCallback)(e=>{N.get(e)?.controller?.abort(),o.cancelMlxModelInstall(e).catch(()=>{}),P(t=>{let n=new Map(t);return n.delete(e),n})},[N]),xe=(0,k.useCallback)(async()=>{let t=W;if(t){G(null),v(null),c(e=>e.filter(e=>e.id!==t)),O(e=>e.filter(e=>e.id!==t)),M(e=>e.filter(e=>e.id!==t));try{await o.deleteMlxModel(t),d(`mlx`),await Q(),e?.()}catch(e){v(`delete failed: ${U(e)}`),Q()}}},[W,Q,e]),Se=(0,k.useMemo)(()=>new Set(n.map(e=>e.id)),[n]),Ce=(0,k.useMemo)(()=>new Set(j.map(e=>e.id)),[j]),we=(0,k.useMemo)(()=>{let e=new Set;for(let t of ue){let n=V(t.manifest);n&&e.add(n.category??`general`)}return[`all`,...[`general`,`coding`,`reasoning`,`vision`,`embedding`].filter(t=>e.has(t))]},[ue]);return(0,A.jsxs)(`div`,{className:`ollama-model-manager`,children:[N.size>0&&(0,A.jsxs)(`div`,{className:`ollama-section`,children:[(0,A.jsx)(`h4`,{children:`Downloading…`}),(0,A.jsx)(`div`,{className:`ollama-pull-list`,children:Array.from(N.values()).map(e=>(0,A.jsx)(ie,{inst:e,onCancel:()=>be(e.catalogId),onRetry:()=>{P(t=>{let n=new Map(t);return n.delete(e.catalogId),n}),R(null),$(e.catalogId)}},e.catalogId))})]}),(0,A.jsx)(E,{items:j.filter(e=>!N.has(e.id)),onUpdate:e=>$(e),onRemove:e=>G(e)}),(0,A.jsx)(y,{items:D.filter(e=>!N.has(e.id)),onResume:e=>$(e),onDelete:e=>G(e)}),z&&(0,A.jsxs)(`div`,{className:`ollama-section`,children:[(0,A.jsxs)(`div`,{className:`gz-status-pill gz-status-pill--warn`,style:{marginBottom:`0.5rem`},children:[`⚠ `,(0,A.jsx)(`code`,{children:z.catalogId}),` is newer on Hugging Face than the version Gezel knows about`]}),(0,A.jsxs)(`p`,{style:{marginBottom:`0.5rem`},children:[`The file `,(0,A.jsx)(`code`,{children:z.file}),` changed upstream, so its checksum no longer matches what this version of Gezel pinned. This is almost always a harmless upstream fix — model authors routinely re-publish chat templates and tokenizer configs — but we can't verify it automatically. You can download the current version now, or wait for a Gezel update with a refreshed catalog.`]}),(0,A.jsxs)(`div`,{style:{display:`flex`,gap:`0.75rem`},children:[(0,A.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:()=>ye(z.catalogId),children:`Download anyway`}),(0,A.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:()=>H(null),children:`Dismiss`})]})]}),L&&(0,A.jsx)(`div`,{className:`ollama-section`,children:(0,A.jsx)(`p`,{className:`error`,style:{marginBottom:`0.5rem`},children:L})}),F&&(0,A.jsx)(`div`,{className:`ollama-section`,children:(0,A.jsxs)(`div`,{className:`gz-status-pill gz-status-pill--warn`,style:{marginBottom:`0.5rem`},children:[`⚠ `,F.id,`: `,F.message]})}),!t&&(0,A.jsx)(C,{engine:`mlx`,onModelsChanged:e}),(n.length>0||p)&&(0,A.jsxs)(`div`,{className:`ollama-section`,children:[(0,A.jsx)(`h4`,{children:t?`Models on this device`:`Local models`}),p&&(0,A.jsx)(`p`,{className:`error`,children:p}),n.length>0&&(0,A.jsx)(`div`,{className:`ollama-model-table-wrap`,children:(0,A.jsxs)(`table`,{className:`ollama-model-table`,children:[(0,A.jsxs)(`colgroup`,{children:[(0,A.jsx)(`col`,{className:`model-name-column`}),(0,A.jsx)(`col`,{}),(0,A.jsx)(`col`,{}),(0,A.jsx)(`col`,{}),(0,A.jsx)(`col`,{}),(0,A.jsx)(`col`,{})]}),(0,A.jsx)(`thead`,{children:(0,A.jsxs)(`tr`,{children:[(0,A.jsx)(`th`,{children:`Name`}),(0,A.jsx)(`th`,{children:`Size`}),(0,A.jsx)(`th`,{children:`Quant`}),(0,A.jsx)(`th`,{title:`Effective per-turn context size after Gezel's configured limit`,children:`Context size`}),(0,A.jsx)(`th`,{title:`Representative startup and decode speed with an approximately 20K-token prompt`,children:`Fitness`}),(0,A.jsx)(`th`,{})]})}),(0,A.jsx)(`tbody`,{children:n.map(e=>{let t=e.updateAvailable===!0,n=!!N.get(e.id),a=`mlx:${e.id}`,c=fe.get(a);return(0,A.jsxs)(k.Fragment,{children:[(0,A.jsxs)(`tr`,{children:[(0,A.jsx)(`td`,{className:`model-name-table-cell`,children:(0,A.jsxs)(`div`,{className:`model-name-cell`,children:[(0,A.jsx)(`code`,{children:e.id}),(0,A.jsx)(`div`,{className:`model-name-meta`,children:t&&(0,A.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,title:e.updateReason??`The catalog ships different model files than the copy on disk. Update to pick them up.`,children:`out of date`})})]})}),(0,A.jsx)(ee,{model:e}),(0,A.jsx)(`td`,{title:i(e.quantization),children:r(e.quantization)}),(0,A.jsx)(`td`,{title:e.effectiveContextWindow?e.overrideContextTokens===void 0?`Gezel will grant up to ${e.effectiveContextWindow.toLocaleString()} tokens per turn${e.contextWindow?`; the model advertises ${e.contextWindow.toLocaleString()} tokens`:``}.`:`You've set this model to ${e.overrideContextTokens.toLocaleString()} tokens per turn; Gezel grants up to what memory allows (currently ${e.effectiveContextWindow.toLocaleString()}).`:e.contextSizingStatus===`restart-required`?`This model is running with a different context window than the current sizing settings resolve to. Restart the local engine (or let it go idle) so Gezel can re-admit it — no memory change needed.`:e.contextSizingStatus===`insufficient-memory`?`The requested context window does not fit in memory safely. Unload another model or free memory before trying again.`:`The effective context size is unavailable.`,children:e.contextSizingStatus===`restart-required`?`Restart needed`:e.contextSizingStatus===`insufficient-memory`?`Won't fit`:(0,A.jsxs)(A.Fragment,{children:[s(e.effectiveContextWindow),e.overrideContextTokens!==void 0&&(0,A.jsx)(`span`,{className:`gz-budget-tag gz-budget-tag-custom model-context-custom-tag`,children:`custom`})]})}),(0,A.jsx)(T,{entry:c,probing:me.includes(a)}),(0,A.jsx)(`td`,{className:`model-actions-table-cell`,children:(0,A.jsxs)(`div`,{className:`model-actions-cell`,children:[(0,A.jsx)(`div`,{className:`model-action-status`,children:e.readOnly&&(0,A.jsx)(`span`,{className:`muted small`,title:`Provided by the machine-wide install (shared asset store). It can't be removed from here — manage it with the machine installer, or install a user-owned copy to shadow it.`,children:`Machine model`})}),(0,A.jsx)(`div`,{className:`model-action-links`,children:(0,A.jsx)(x,{engine:`mlx`,model:{...e,updateAvailable:t},updating:n,contextSupported:le,contextEditorOpen:Y===e.id,onToggleContextEditor:()=>ce(t=>t===e.id?null:e.id),fitnessAction:S(c,me.includes(a),()=>{o.runModelFitnessProbe(`mlx`,e.id).then(()=>Z()).catch(()=>{})}),onUpdate:()=>$(e.id),updateLabel:{idle:`Download again`,busy:`Downloading…`},onDelete:()=>G(e.id)})})]})})]}),Y===e.id&&(0,A.jsx)(`tr`,{className:`model-context-editor-row`,children:(0,A.jsx)(`td`,{colSpan:6,children:(0,A.jsx)(w,{engine:`mlx`,model:e,onSaved:Q})})})]},e.id)})})]})})]}),(0,A.jsxs)(`div`,{className:`ollama-section ollama-section--flat ollama-section--download`,children:[(0,A.jsx)(`h4`,{children:`Download a model`}),(0,A.jsxs)(`p`,{className:`muted small`,style:{marginTop:0},children:[`Models are hosted by`,` `,(0,A.jsx)(`a`,{href:`https://huggingface.co`,target:`_blank`,rel:`noreferrer`,style:{color:`inherit`},children:`Hugging Face`}),`, a community library of open, freely available AI models. Your device downloads them directly.`]}),(0,A.jsxs)(`p`,{className:`muted small`,children:[K?`Models that may not fit this machine, and retired models, are hidden by default. `:`Retired models are hidden by default. `,(0,A.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:()=>oe(e=>!e),style:{padding:0},children:q?K?`Hide retired and oversized models`:`Hide retired models`:`Show all models`})]}),(0,A.jsx)(`div`,{className:`provider-switch`,style:{marginBottom:`0.5rem`},children:we.map(e=>(0,A.jsx)(`button`,{type:`button`,className:`provider-pill${J===e?` provider-pill-active`:``}`,onClick:()=>se(e),children:e===`all`?`All`:e[0]?.toUpperCase()+e.slice(1)},e))}),(0,A.jsx)(h,{kind:`chat-model`,emptyMessage:`No MLX-format entries in the catalog yet.`,onItemsLoaded:de,tagTooltips:re,filter:e=>{let t=V(e.manifest);return!(!t||!q&&a(t)||J!==`all`&&(t.category??`general`)!==J||!q&&K&&!te(t.mlx,K.usableBytes))},action:e=>{let t=V(e.manifest);if(!t)return null;let n=Se.has(t.id),r=Ce.has(t.id),i=N.get(t.id),a=i&&i.totalBytesAll>0?Math.min(100,Math.round(i.bytesWrittenAll/i.totalBytesAll*100)):null,o=K?!te(t.mlx,K.usableBytes):!1;return(0,A.jsxs)(`div`,{className:`catalog-ollama-action`,children:[(0,A.jsxs)(`div`,{className:`catalog-ollama-meta`,children:[(0,A.jsxs)(`div`,{className:`catalog-ollama-specs muted small`,children:[(0,A.jsx)(g,{repo:t.mlx.huggingfaceRepo}),(0,A.jsx)(`span`,{children:`·`}),(0,A.jsx)(`span`,{children:t.parameterSize}),(0,A.jsx)(`span`,{children:`·`}),(0,A.jsx)(`span`,{children:ne(t.mlx.approxSizeBytes)}),B(t.releasedAt)&&(0,A.jsxs)(A.Fragment,{children:[(0,A.jsx)(`span`,{children:`·`}),(0,A.jsx)(`span`,{children:B(t.releasedAt)})]})]}),(0,A.jsxs)(`div`,{className:`catalog-ollama-pills`,children:[(0,A.jsx)(b,{manifest:t,fallbackHref:_(t.mlx.huggingfaceRepo)}),o&&(0,A.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,title:`Larger than your estimated inference budget — may run slowly or fail.`,children:`may not fit`})]})]}),(0,A.jsx)(`button`,{type:`button`,disabled:n||r||!!i,onClick:()=>$(t.id),children:n?`On device`:i?i.phase===`downloading`?a===null?`Downloading…`:`Downloading… ${a}%`:i.phase===`verifying`?`Verifying…`:`Reading metadata…`:r?`Needs attention above`:`Download`})]})}})]}),(0,A.jsxs)(`div`,{className:`ollama-section ollama-section--flat`,children:[(0,A.jsx)(m,{}),(0,A.jsx)(`span`,{className:`muted small`,style:{marginLeft:`0.75rem`},children:`Import from a gezel local model package`})]}),(0,A.jsx)(l,{open:W!==null,title:`Delete ${W??``}?`,message:`This removes the downloaded model from your device. It stays available in the catalog — you can download it again any time.`,confirmLabel:`Delete`,danger:!0,onConfirm:xe,onCancel:()=>G(null)})]})}function ie({inst:e,onCancel:t,onRetry:n}){let r=e.totalBytesAll>0,i=r?Math.min(100,Math.round(e.bytesWrittenAll/e.totalBytesAll*100)):0,a;if(e.error)a=e.error;else if(e.retrying){let t=Math.max(1,Math.round(e.retrying.delayMs/1e3)),n=e.fileCount>1?` on shard ${e.fileIndex}/${e.fileCount}`:``;a=`${e.retrying.reason}${n} — retrying in ${t}s (attempt ${e.retrying.attempt}/${e.retrying.maxAttempts})`}else a=e.phase===`downloading`?r?`Downloading ${c(e.bytesWrittenAll)} of ${c(e.totalBytesAll)} (${i}%)`:e.bytesWrittenAll>0?`Downloading ${c(e.bytesWrittenAll)}…`:`Preparing download…`:e.phase===`verifying`?`Checking download${e.file?` (${e.file})`:`…`}`:`Reading model info…`;let o=e.phase!==`downloading`||!r;return(0,A.jsx)(v,{title:(0,A.jsx)(`code`,{children:e.catalogId}),status:a,percent:o?null:i,tone:e.error?`error`:e.retrying?`warning`:`normal`,onCancel:t,onRetry:n})}function U(e){return e instanceof Error?e.message:String(e)}var W=typeof navigator<`u`&&/Mac/.test(navigator.platform)&&(navigator.userAgentData?.architecture===`arm`||/Mac.*Apple/i.test(navigator.userAgent));function G({config:e,onConfigChanged:t}){let[n,r]=(0,k.useState)(e?.mlxBaseUrl??``),[i,a]=(0,k.useState)(e?.mlxModelPath??``),[s,c]=(0,k.useState)(e?.mlxPackageSpec??``),[l,u]=(0,k.useState)(null),[d,f]=(0,k.useState)([]),[p,m]=(0,k.useState)(`idle`),[h,g]=(0,k.useState)(null),[_,v]=(0,k.useState)(`idle`);(0,k.useEffect)(()=>{r(e?.mlxBaseUrl??``)},[e?.mlxBaseUrl]),(0,k.useEffect)(()=>{a(e?.mlxModelPath??``)},[e?.mlxModelPath]),(0,k.useEffect)(()=>{c(e?.mlxPackageSpec??``)},[e?.mlxPackageSpec]);let y=(0,k.useCallback)(async()=>{try{let e=await o.getMlxRuntime();u(e)}catch{u(null)}},[]);(0,k.useEffect)(()=>{y()},[y]);let b=(0,k.useCallback)(async()=>{try{let e=await o.listMlxModels();f(e.models)}catch{}},[]);(0,k.useEffect)(()=>{b()},[b]);let x=(0,k.useCallback)(()=>{b(),y()},[b,y]),S=(0,k.useCallback)(async()=>{v(`resetting`);try{await o.resetMlxRuntime(),v(`done`),setTimeout(()=>v(`idle`),3e3),y()}catch(e){v(`idle`),g(e instanceof Error?e.message:String(e))}},[y]),C=(0,k.useCallback)(async()=>{let e=n.trim();m(`saving`);try{t(await o.updateConfig({mlxBaseUrl:e===``?null:e})),m(`saved`),setTimeout(()=>m(`idle`),1200)}catch{m(`idle`)}},[n,t]),w=(0,k.useCallback)(async()=>{let e=i.trim();m(`saving`);try{t(await o.updateConfig({mlxModelPath:e===``?null:e})),m(`saved`),setTimeout(()=>m(`idle`),1200)}catch{m(`idle`)}},[i,t]),T=(0,k.useCallback)(async()=>{let e=s.trim();m(`saving`);try{t(await o.updateConfig({mlxPackageSpec:e===``?null:e})),m(`saved`),setTimeout(()=>m(`idle`),1200)}catch{m(`idle`)}},[s,t]),E=(0,k.useCallback)(async e=>{m(`saving`);try{t(await o.updateConfig({mlxKvBits:e===0?null:e})),m(`saved`),setTimeout(()=>m(`idle`),1200)}catch{m(`idle`)}},[t]),ee=(0,k.useCallback)(async n=>{m(`saving`);try{t(await o.updateConfig({defaultModel:{...e?.defaultModel,mlx:n??void 0}})),m(`saved`),setTimeout(()=>m(`idle`),1200)}catch{m(`idle`)}},[e?.defaultModel,t]),j=!!e?.mlxBaseUrl;return(0,A.jsxs)(`div`,{children:[(0,A.jsxs)(`section`,{style:{marginBottom:`2rem`},children:[(0,A.jsx)(`h3`,{children:`This Mac (Apple MLX)`}),(0,A.jsx)(`p`,{className:`muted`,style:{marginTop:0},children:`On-device AI powered by Apple's MLX framework, making the best use of the hardware you already have — in many cases the best choice of engine for your Mac. Your conversations stay on your computer: no account to set up, no data sent to the cloud.`}),(0,A.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.75rem`,alignItems:`center`},children:[(0,A.jsx)(`span`,{className:`muted small`,children:`Status:`}),(0,A.jsx)(`span`,{className:`gz-status-pill gz-status-pill--ok`,children:`ready`})]}),!W&&(0,A.jsx)(`div`,{className:`gz-status-pill gz-status-pill--warn`,style:{marginTop:`0.5rem`,display:`inline-block`},children:`This machine doesn't look like Apple Silicon — chat turns routed to MLX will error out at send time.`}),j&&(0,A.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.75rem`},children:[(0,A.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,title:`External engine: ${e?.mlxBaseUrl}`,children:`using external engine`}),p===`saved`&&(0,A.jsx)(`span`,{className:`muted small`,children:`saved ✓`})]})]}),d.length>1&&(0,A.jsxs)(`section`,{style:{marginBottom:`2rem`},children:[(0,A.jsx)(`h4`,{children:`Default model`}),(0,A.jsx)(`p`,{className:`muted small`,style:{marginTop:0},children:`Which local model new chat sessions use when a gezel doesn't pin one.`}),(0,A.jsx)(`div`,{className:`new-row`,style:{marginTop:`0.5rem`},children:(0,A.jsxs)(`select`,{"aria-label":`Default model`,value:e?.defaultModel?.mlx??``,onChange:e=>void ee(e.target.value||void 0),children:[(0,A.jsx)(`option`,{value:``,children:`First local model`}),d.map(e=>(0,A.jsxs)(`option`,{value:e.id,children:[e.name,` (`,e.id,`)`]},e.id))]})})]}),(0,A.jsx)(`section`,{style:{marginBottom:`2rem`},children:(0,A.jsx)(H,{onModelsChanged:x})}),(0,A.jsx)(O,{provider:`mlx`}),(0,A.jsxs)(`section`,{style:{marginBottom:`2rem`},children:[(0,A.jsx)(`h4`,{style:{marginBottom:`0.5rem`},children:`Concurrent replicas`}),(0,A.jsx)(`p`,{className:`muted small`,style:{marginTop:0},children:`Run multiple copies of the same model so unrelated sessions don't queue behind each other. Weights are shared by the OS via mmap so disk cost stays at one model file; resident memory grows because each clone keeps its own KV cache and activations.`}),(0,A.jsx)(D,{provider:`mlx`,modelId:e?.defaultModel?.mlx??null,config:e,onConfigChanged:t})]}),h&&(0,A.jsxs)(`div`,{className:`muted small`,style:{color:`#ff9b9b`,marginTop:`1rem`},role:`alert`,children:[h,` `,(0,A.jsx)(`button`,{type:`button`,onClick:()=>g(null),children:`dismiss`})]}),(0,A.jsx)(`section`,{style:{marginTop:`2rem`},children:(0,A.jsx)(R,{providerName:`mlx`,label:`This Mac AI`,configuredBudgetMb:e?.cacheBudgetMb?.mlx})}),(0,A.jsxs)(`details`,{className:`mlx-advanced`,style:{marginTop:`2rem`},children:[(0,A.jsx)(`summary`,{style:{cursor:`pointer`},children:(0,A.jsx)(`strong`,{children:`Advanced`})}),(0,A.jsxs)(`section`,{style:{marginTop:`1.25rem`},children:[(0,A.jsx)(`h4`,{style:{marginBottom:`0.35rem`},children:`Python runtime`}),l?(0,A.jsx)(`div`,{className:`muted small`,style:{marginTop:`0.25rem`},children:l.source===null?(0,A.jsxs)(A.Fragment,{children:[(0,A.jsx)(`strong`,{children:`No Python runtime available.`}),` `,l.reason??`Install Python 3.11 or wait for a packaged build that bundles uv.`]}):(0,A.jsxs)(A.Fragment,{children:[`Source: `,(0,A.jsx)(`code`,{children:l.source}),l.uvVersion&&(0,A.jsxs)(A.Fragment,{children:[` `,`· uv `,(0,A.jsx)(`code`,{children:l.uvVersion})]}),l.pythonVersion&&(0,A.jsxs)(A.Fragment,{children:[` `,`· Python `,(0,A.jsx)(`code`,{children:l.pythonVersion})]}),l.installerPath&&(0,A.jsxs)(A.Fragment,{children:[` `,`· `,(0,A.jsx)(`span`,{title:l.installerPath,children:`installer at path`})]})]})}):(0,A.jsx)(`div`,{className:`muted small`,children:`Probing…`}),(0,A.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.5rem`,alignItems:`center`},children:[(0,A.jsx)(`button`,{type:`button`,onClick:()=>void S(),disabled:_===`resetting`,children:_===`resetting`?`Resetting…`:`Reset gezel Python environment`}),_===`done`?(0,A.jsx)(`span`,{className:`gz-status-pill gz-status-pill--ok`,children:`venv was reset ✓`}):(0,A.jsx)(`span`,{className:`muted small`,children:"Deletes the `mlx` venv; the next chat turn re-provisions it."})]})]}),(0,A.jsxs)(`section`,{style:{marginTop:`1.25rem`},children:[(0,A.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.75rem`,alignItems:`center`},children:[(0,A.jsx)(`label`,{className:`muted`,style:{fontSize:`0.9rem`,minWidth:`12rem`},children:`External mlx_lm.server URL`}),(0,A.jsx)(`input`,{type:`text`,placeholder:`e.g. http://127.0.0.1:8000 (leave blank for supervised)`,value:n,onChange:e=>r(e.target.value),style:{flex:1}}),(0,A.jsx)(`button`,{type:`button`,disabled:p===`saving`||n===(e?.mlxBaseUrl??``),onClick:()=>void C(),children:`Save`})]}),(0,A.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.5rem`,alignItems:`center`},children:[(0,A.jsx)(`label`,{className:`muted`,style:{fontSize:`0.9rem`,minWidth:`12rem`},children:`Override model directory`}),(0,A.jsx)(`input`,{type:`text`,placeholder:`Absolute path to an MLX model dir`,value:i,onChange:e=>a(e.target.value),style:{flex:1}}),(0,A.jsx)(`button`,{type:`button`,disabled:p===`saving`||i===(e?.mlxModelPath??``),onClick:()=>void w(),children:`Save`})]}),(0,A.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.5rem`,alignItems:`center`},children:[(0,A.jsx)(`label`,{className:`muted`,style:{fontSize:`0.9rem`,minWidth:`12rem`},children:`mlx-lm package spec`}),(0,A.jsx)(`input`,{type:`text`,placeholder:`e.g. mlx-lm==0.25.3 (blank → latest)`,value:s,onChange:e=>c(e.target.value),style:{flex:1}}),(0,A.jsx)(`button`,{type:`button`,disabled:p===`saving`||s===(e?.mlxPackageSpec??``),onClick:()=>void T(),children:`Save`})]}),(0,A.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.5rem`,alignItems:`center`},children:[(0,A.jsx)(`label`,{className:`muted`,style:{fontSize:`0.9rem`,minWidth:`12rem`},children:`KV cache quantization`}),(0,A.jsxs)(`select`,{value:String(e?.mlxKvBits??0),onChange:e=>void E(Number(e.target.value)),style:{flex:1},children:[(0,A.jsx)(`option`,{value:`0`,children:`Off — full precision (default)`}),(0,A.jsx)(`option`,{value:`8`,children:`8-bit — about half the memory, near-lossless`}),(0,A.jsx)(`option`,{value:`6`,children:`6-bit — smaller still`}),(0,A.jsx)(`option`,{value:`4`,children:`4-bit — smallest, some quality loss`})]})]}),(0,A.jsx)(`p`,{className:`muted small`,style:{marginTop:`0.35rem`},children:`Compresses the conversation history the model keeps in memory. That history is the biggest cost in a long chat — on a large model with a 256K context it can outweigh the model itself — and 8-bit roughly halves it at close to no quality cost. Only applies while the engine serves one chat at a time; when it is set up to handle several at once, the history stays at full precision. Takes effect the next time the engine starts.`})]})]})]})}export{G as MlxSettings};
@@ -0,0 +1 @@
1
+ import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{n as t,t as n}from"./jsx-runtime-CEpd2cAX.js";import{N as r,r as i,rn as a,ut as o}from"./dist-BqGwkOe5.js";import{t as s}from"./api-BPraLwsh.js";import{d as c,l,m as u,p as d,s as f}from"./primitives-CWrGZpPI.js";import{a as p,o as m,t as h}from"./model-inventory-ykSm_IT5.js";import{t as g}from"./GezelJsonEditor-7vDGyBib.js";var _=e(t(),1),v={type:`number`,title:`Temperature`,description:`How adventurous the model is when picking words. Low values (0–0.3) make replies steady and repeatable — good for code, math, structured output. Mid values (0.5–0.9) feel like a thoughtful conversation. High values (1.0+) get creative but can drift off-topic or start rambling. 0 picks the single most likely word every time.`,minimum:0,maximum:2,multipleOf:.05},y={type:`number`,title:`top_p (nucleus)`,description:`Trims the long tail of unlikely word choices. 0.95 keeps the model honest while letting it surprise you — the modern default. Lower values (0.7–0.85) make replies more predictable and stay in the safe zone. Higher values (close to 1) let weirder picks through. Usually tune temperature first, top_p second.`,minimum:0,maximum:1,multipleOf:.01},b={type:`integer`,title:`top_k`,description:`A hard ceiling on how many word choices the model considers at each step. 20 is what Qwen recommends for thinking mode. 64 is Gemma's default. 1 means 'always pick the single most likely word' — deterministic but flat. Lower top_k = more predictable; higher = more variety.`,minimum:0,maximum:1e3},x={type:`number`,title:`min_p`,description:`A floor on word probability — filters out the really unlikely tokens regardless of top_k. 0 disables. 0.05 is a mild filter that prevents the model from grabbing genuinely rare tokens. Most users leave this at 0 and tune temperature + top_p instead.`,minimum:0,maximum:1,multipleOf:.01},S={type:`integer`,title:`Max reply length (tokens)`,description:`Hard ceiling on how long one reply can be. Counts every word, punctuation mark, and reasoning token. Most chat turns fit in 2k–8k. Reasoning models that 'think out loud' need 16k+ to leave room for the actual answer after the thinking trace. Hitting this cap mid-reply cuts the model off.`,minimum:1,maximum:131072},C={type:`integer`,title:`Seed`,description:`Lock in a specific run. Same seed + same prompt = (usually) the same reply, so you can A/B test prompt changes or reproduce a bug. Leave blank for random. Cloud providers honor seed on a best-effort basis; local engines are stricter.`},w={type:`number`,title:`Repetition penalty`,description:`Punishes the model for re-using words it just said. 1.0 = off (the model is allowed to repeat freely). 1.1 = mild — catches 'I will… I'll… I will…' loops. Push above 1.2 and the model starts dodging legitimate repeats (the word 'the' starts feeling rare), and replies feel oddly stilted.`,minimum:0,maximum:3,multipleOf:.05},T={type:`integer`,title:`Repetition window (tokens)`,description:`How far back the repetition penalty looks. 20–64 catches recent loops without affecting older context. Larger windows (256+) penalize re-using words from much earlier in the chat — usually too aggressive for conversation.`,minimum:1,maximum:8192},E={type:`number`,title:`Frequency penalty`,description:`Penalty that scales with how often a word has already appeared in this reply. Positive values (0.3–0.8) discourage repeating common words; negative values encourage repetition. -2 to 2; usually 0.`,minimum:-2,maximum:2,multipleOf:.05},D={type:`number`,title:`Presence penalty`,description:`Penalty applied once any word has appeared at all in this reply (not scaled by count). Positive values (0.3–0.8) push the model toward new vocabulary; useful for brainstorming. -2 to 2; usually 0.`,minimum:-2,maximum:2,multipleOf:.05},O={type:`object`,title:`DRY anti-repetition (llama only)`,description:`Don't-Repeat-Yourself: catches longer phrase loops that simple repetition penalty misses. Helpful for small local models that get stuck repeating whole sentences. Set multiplier to 0 to disable.`,properties:{multiplier:{type:`number`,title:`Strength`,description:`How hard to penalize repeats. 0 = off. 0.8 is a reasonable starting point — strong enough to break loops without hurting normal repetition.`,minimum:0,maximum:5,multipleOf:.05},base:{type:`number`,title:`Penalty curve`,description:`How fast the penalty grows for longer repeated sequences. Higher = more aggressive on long repeats. 1.75 is the upstream default.`,minimum:0,maximum:5,multipleOf:.05},allowedLength:{type:`integer`,title:`Free length`,description:`Repeats shorter than this don't get penalized. 2 = allow 2-token repeats (small phrases), penalize anything longer.`,minimum:0,maximum:64}}},k={type:`object`,title:`XTC sampler (llama only)`,description:`Exclude-Top-Choices: occasionally throws away the most likely word and picks from the rest. Adds personality and surprise to creative writing. Skip this if you want consistency.`,properties:{probability:{type:`number`,title:`Trigger rate`,description:`How often XTC fires. 0 = never. 0.5 = half the time. Higher values make replies less predictable.`,minimum:0,maximum:1,multipleOf:.01},threshold:{type:`number`,title:`Activation threshold`,description:`Only fires when the top word is more likely than this. 0.1 = activate when the model is fairly sure (most of the time); higher values restrict XTC to high-confidence moments.`,minimum:0,maximum:1,multipleOf:.01}}},A={type:`object`,title:`Reasoning`,description:`Controls how much the model 'thinks out loud' before answering.`,properties:{effort:{type:`string`,enum:[`low`,`medium`,`high`],title:`Reasoning effort`,description:`How hard the model works before replying. Low = quick takes (fast, cheap). Medium = balanced (most common default). High = deep deliberation (slower, more thorough — best for math, code, complex planning). Maps to OpenAI's reasoning.effort and Anthropic's thinking.budget_tokens behind the scenes.`,squisq:{control:`segmented`}},thinkingBudget:{type:`integer`,title:`Thinking budget (tokens)`,description:`Explicit cap on how many tokens the model can spend thinking before it has to answer. Anthropic Claude and Nemotron use this directly. Wins over 'effort' when both are set. Typical values: 2k for quick, 8k for medium, 24k+ for deep reasoning.`,minimum:1,maximum:65536},enableThinking:{type:`boolean`,title:`Show reasoning`,description:`On = the model writes out its thinking before the final answer (often visible as a collapsible 'thinking' block). Off = the model goes straight to the answer. Mainly affects dual-mode local models like Qwen3 and Nemotron Nano/Super — cloud thinking models infer from the reasoning effort/budget.`}}},j={type:`object`,title:`Structured output`,description:`Force the model to produce machine-readable output instead of prose.`,properties:{responseFormat:{type:`string`,enum:[`text`,`json_object`],title:`Output format`,description:`Text = normal prose (default). JSON = the model must emit syntactically-valid JSON. Combine with a JSON Schema below to pin the exact shape.`,squisq:{control:`segmented`,enumLabels:{text:`Text`,json_object:`JSON`}}}}},M={type:`string`,enum:[`auto`,`required`,`none`],title:`Tool calling`,description:`Auto = the model decides whether to call a tool (normal). Required = the model MUST call a tool this turn (good for forcing structured handoffs). None = tools are hidden from the model — pure chat.`,squisq:{control:`segmented`}},N={type:`object`,title:`Reasoning prompt tags`,description:`Markers a user can include in a message to flip reasoning on/off for just that turn. Qwen recognizes /think and /no_think by default.`,properties:{enableThinkingTag:{type:`string`,title:`Enable tag`,description:"Example: `/think`. Adding this to your message turns thinking ON for that turn."},disableThinkingTag:{type:`string`,title:`Disable tag`,description:"Example: `/no_think`. Adding this to your message turns thinking OFF for that turn."}}};function P(e){return{type:`object`,title:`When thinking is on, use these instead`,description:`Some models like Qwen3 and Nemotron Nano want different sampling when reasoning. Only fill in the fields you want to change for thinking mode — the rest fall through to your main Sampling values above.`,properties:e,squisq:{hidden:{field:`reasoning.enableThinking`,truthy:!1}}}}var F={temperature:v,topP:y,topK:b,maxTokens:S,seed:C,frequencyPenalty:E,presencePenalty:D},I={type:`object`,title:`Structured output`,properties:{responseFormat:j.properties.responseFormat,jsonSchema:{type:`object`,title:`JSON Schema`,description:`OpenAI strict mode. Leave empty for free-form JSON.`,additionalProperties:!0}}},L={type:`object`,title:`Advanced tuning (cloud)`,description:`Per-turn sampling, structured output, and reasoning controls. Empty fields fall through to the catalog default. Fields the active provider doesn't support are silently dropped at request build.`,properties:{sampling:{type:`object`,title:`Sampling`,properties:F},samplingWhenThinking:P(F),reasoning:A,output:I,toolChoice:M}},R={temperature:v,topP:y,topK:b,minP:x,maxTokens:S,seed:C,repetitionPenalty:w,repetitionContext:T,frequencyPenalty:E,presencePenalty:D,dry:O,xtc:k},ee={...A,properties:{enableThinking:A.properties.enableThinking}},te={type:`object`,title:`Structured output`,properties:{responseFormat:j.properties.responseFormat,jsonSchema:{type:`object`,title:`JSON Schema`,description:"Pin output to a JSON Schema. Drives llama `--json-schema`. Leave empty for free-form JSON.",additionalProperties:!0},grammar:{type:`string`,title:`GBNF grammar`,description:`Last-resort structured-output knob. llama-only. Multi-line GBNF source.`,maxLength:4096,squisq:{control:`multiline`}}}},ne={type:`object`,title:`Advanced tuning (llama)`,description:`Per-turn sampling, structured output, and reasoning controls. Empty fields fall through to the catalog default.`,properties:{sampling:{type:`object`,title:`Sampling`,properties:R},samplingWhenThinking:P(R),reasoning:ee,output:te,toolChoice:M,promptTags:N}},z={temperature:v,topP:y,topK:b,minP:x,maxTokens:S,seed:C,repetitionPenalty:w,repetitionContext:T},re={...A,properties:{enableThinking:A.properties.enableThinking}},ie={type:`object`,title:`Advanced tuning (MLX)`,description:`Per-turn sampling and reasoning controls. Empty fields fall through to the catalog default.`,properties:{sampling:{type:`object`,title:`Sampling`,properties:z},samplingWhenThinking:P(z),reasoning:re,output:j,toolChoice:M,promptTags:N}},B={temperature:v,topP:y,topK:b,minP:x,maxTokens:S,seed:C,repetitionPenalty:w,repetitionContext:T,frequencyPenalty:E,presencePenalty:D},ae={...A,properties:{enableThinking:A.properties.enableThinking}},oe={type:`object`,title:`Structured output`,properties:{responseFormat:j.properties.responseFormat,jsonSchema:{type:`object`,title:`JSON Schema`,description:"Pin output to a JSON Schema. Maps to Ollama 0.5+ `format: <schema>`. Leave empty for free-form JSON.",additionalProperties:!0}}},se={type:`object`,title:`Advanced tuning (Ollama)`,description:`Per-turn sampling, structured output, and reasoning controls. Empty fields fall through to the catalog default.`,properties:{sampling:{type:`object`,title:`Sampling`,properties:B},samplingWhenThinking:P(B),reasoning:ae,output:oe,promptTags:N}};function ce(e){switch(e){case`llama-cpp`:case`ds4`:return ne;case`mlx`:return ie;case`ollama`:return se;case`openai`:case`anthropic`:case`anthropic-cli`:case`codex-cli`:case`copilot`:return L;case`remote`:return L;default:return e}}var V=n();function le({provider:e,override:t,inherited:n,onSave:r,scopeLabel:s=`this scope`,disabled:c,tuningProfileId:l}){let u=(0,_.useMemo)(()=>ce(e),[e]),d=(0,_.useMemo)(()=>fe(u,n??{}),[u,n]),f=(0,_.useMemo)(()=>H(n??{},t??{}),[n,t]),[p,m]=(0,_.useState)(f),[h,v]=(0,_.useState)(!1),[y,b]=(0,_.useState)(null);(0,_.useEffect)(()=>{m(f)},[f]);let x=(0,_.useCallback)(e=>{m(e??{})},[]),S=(0,_.useMemo)(()=>ue(p,n??{}),[p,n]),C=S!==null,w=(0,_.useMemo)(()=>S?G(S):`(none)`,[S]),T=(0,_.useMemo)(()=>G(p)||`(provider defaults)`,[p]),E=(0,_.useMemo)(()=>G(n??{})||`(provider defaults)`,[n]),D=(0,_.useMemo)(()=>{if(l)return a(l,Object.keys(n?.profiles??{}))},[l,n]),O=(0,_.useMemo)(()=>{if(!l)return null;if(D){let e=o(D)?i[D].label:D,t=D!==l,n=o(l)?i[l].label:l;return t?`${e} (fallback from ${n} — model doesn't define it)`:e}return`${l} (not defined on this model — base tuning applies)`},[l,D]),k=(0,_.useCallback)(async()=>{v(!0),b(null);try{await r(S)}catch(e){b(e instanceof Error?e.message:String(e))}finally{v(!1)}},[S,r]),A=(0,_.useCallback)(async()=>{v(!0),b(null);try{await r(null),m(n??{})}catch(e){b(e instanceof Error?e.message:String(e))}finally{v(!1)}},[n,r]);return(0,V.jsxs)(`div`,{className:`tuning-panel`,children:[(0,V.jsxs)(`div`,{className:`tuning-panel-summary small`,style:{display:`flex`,flexDirection:`column`,gap:`0.25rem`,marginBottom:`0.5rem`},children:[O&&(0,V.jsxs)(`div`,{children:[(0,V.jsx)(`strong`,{children:`Active voice:`}),` `,(0,V.jsx)(`span`,{className:`muted`,children:O})]}),(0,V.jsxs)(`div`,{children:[(0,V.jsx)(`strong`,{children:`Effective now:`}),` `,(0,V.jsx)(`span`,{className:`muted`,children:T})]}),(0,V.jsxs)(`div`,{children:[(0,V.jsx)(`strong`,{children:`Inherited default:`}),` `,(0,V.jsx)(`span`,{className:`muted`,children:E})]}),(0,V.jsxs)(`div`,{children:[(0,V.jsxs)(`strong`,{children:[`Your override for `,s,`:`]}),` `,(0,V.jsx)(`span`,{className:C?``:`muted`,children:w})]})]}),(0,V.jsx)(g,{schema:d,value:p,onChange:x,density:`compact`}),(0,V.jsxs)(`div`,{className:`tuning-panel-actions`,style:{marginTop:`0.5rem`},children:[(0,V.jsx)(`button`,{type:`button`,onClick:k,disabled:c||h,children:h?`Saving…`:C?`Save override for ${s}`:`Save (no override)`}),t&&Object.keys(t).length>0&&(0,V.jsx)(`button`,{type:`button`,onClick:A,disabled:c||h,className:`muted`,style:{marginLeft:`0.5rem`},children:`Reset to inherited defaults`})]}),y&&(0,V.jsx)(`div`,{className:`tuning-panel-error small error`,style:{marginTop:`0.25rem`},children:y})]})}function H(e,t){let n={...e};for(let[e,r]of Object.entries(t)){if(r===void 0)continue;let t=n[e];t&&typeof t==`object`&&!Array.isArray(t)&&r&&typeof r==`object`&&!Array.isArray(r)?n[e]=H(t,r):n[e]=r}return n}function ue(e,t){let n=de(e,t);return n===null?null:n}function de(e,t){let n={},r=!1;for(let[i,a]of Object.entries(e)){let e=t[i];if(a!=null)if(typeof a==`object`&&!Array.isArray(a)&&typeof e==`object`&&e&&!Array.isArray(e)){let t=de(a,e);t!==null&&(n[i]=t,r=!0)}else U(a,e)||(n[i]=a,r=!0)}return r?n:null}function U(e,t){return e===t?!0:typeof e==typeof t?Array.isArray(e)&&Array.isArray(t)?e.length===t.length&&e.every((e,n)=>U(e,t[n])):JSON.stringify(e)===JSON.stringify(t):!1}function fe(e,t){return W(e,t)}function W(e,t){let n={...e};if(n.properties){let e={};for(let[r,i]of Object.entries(n.properties))e[r]=W(i,t&&typeof t==`object`?t[r]:void 0);n.properties=e}if(n.type!==`object`&&t!=null){let e=pe(t);if(e!==null){let t=n.description??``;n.description=t?`${t}\n\nDefault: ${e}`:`Default: ${e}`}}return n}function pe(e){return typeof e==`number`?String(e):typeof e==`boolean`?e?`on`:`off`:typeof e==`string`?e:null}function G(e){let t=[];if(e.sampling){let n=e.sampling,r=[];n.temperature!==void 0&&r.push(`temp ${n.temperature}`),n.topP!==void 0&&r.push(`top_p ${n.topP}`),n.topK!==void 0&&r.push(`top_k ${n.topK}`),n.minP!==void 0&&r.push(`min_p ${n.minP}`),n.maxTokens!==void 0&&r.push(`max ${n.maxTokens}`),n.seed!==void 0&&r.push(`seed ${n.seed}`),n.repetitionPenalty!==void 0&&r.push(`rep ${n.repetitionPenalty}`),n.frequencyPenalty!==void 0&&r.push(`freq ${n.frequencyPenalty}`),n.presencePenalty!==void 0&&r.push(`pres ${n.presencePenalty}`),r.length>0&&t.push(r.join(`, `))}if(e.reasoning){let n=e.reasoning;n.effort&&t.push(`effort ${n.effort}`),n.thinkingBudget!==void 0&&t.push(`budget ${n.thinkingBudget}`),n.enableThinking===!0&&t.push(`thinking on`),n.enableThinking===!1&&t.push(`thinking off`)}return e.output?.responseFormat&&e.output.responseFormat!==`text`&&t.push(`format ${e.output.responseFormat}`),e.toolChoice&&t.push(`tools ${e.toolChoice}`),e.samplingWhenThinking&&Object.keys(e.samplingWhenThinking).length>0&&t.push(`+thinking sampling`),e.promptTags?.enableThinkingTag&&t.push(`tag ${e.promptTags.enableThinkingTag}`),t.join(` · `)}var K=new Map,q=new Map,J=new Map;function Y(e){J.set(e,(J.get(e)??0)+1),q.delete(e),K.delete(e)}async function X(e,t=!1){if(t&&Y(e),!t){let t=q.get(e);if(t)return t;let n=K.get(e);if(n)return n}let n=J.get(e)??0,r=(e===`remote`?me():s.listProviderModels(e,t?{refresh:!0}:void 0).then(e=>e.models)).then(t=>((J.get(e)??0)===n&&q.set(e,t),t)).finally(()=>{K.get(e)===r&&K.delete(e)});return K.set(e,r),r}async function me(){let{remotes:e}=await s.listRemotes(),t=[];for(let n of e)try{let{models:e}=await s.listRemoteModels(n.remoteId);for(let r of e)t.push({id:r.id,name:`${n.displayName} · ${r.name}`,...r.supportsTools===void 0?{}:{supportsTools:r.supportsTools},...r.supportsReasoning===void 0?{}:{supportsReasoning:r.supportsReasoning},...r.contextWindow?{contextWindow:r.contextWindow}:{},...r.parameterSize?{parameterSize:r.parameterSize}:{}})}catch{}return t}function Z(e){return e===`mlx`||e===`llama-cpp`}function he(e){return e===`mlx`||e===`llama-cpp`||e===`ds4`}var Q=null,$=null;async function ge(){return Q||$||($=s.listModelFitness().then(e=>(Q=new Map(e.records.map(e=>[e.key,e])),Q)).finally(()=>{$=null}),$)}async function _e(e){let[t,n]=await Promise.all([e===`mlx`?s.listMlxModels():s.listLlamaCppModels(),e===`mlx`?s.listMlxActiveInstalls():s.listLlamaCppActiveInstalls()]);return t.models.length===0?{activeInstallsCount:n.installs.length}:null}function ve({provider:e,value:t,onChange:n,placeholder:i=`Provider default`}){let[a,o]=(0,_.useState)(q.get(e)??null),[s,g]=(0,_.useState)(!q.has(e)),[v,y]=(0,_.useState)(null),[b,x]=(0,_.useState)(null),[S,C]=(0,_.useState)(!1),[w,T]=(0,_.useState)(t??``),[E,D]=(0,_.useState)(Q),[O,k]=(0,_.useState)(0),A=(0,_.useRef)(null);(0,_.useEffect)(()=>{let t=t=>{let n=p(t);n===e&&(A.current=n,Y(e),k(e=>e+1))};return window.addEventListener(h,t),()=>window.removeEventListener(h,t)},[e]),(0,_.useEffect)(()=>{if(e!==`llama-cpp`&&e!==`ds4`)return;let t=!1;return ge().then(e=>{t||D(e)}).catch(()=>{}),()=>{t=!0}},[e]),(0,_.useEffect)(()=>{g(!q.has(e)),o(q.get(e)??null),y(null),x(null),C(!1);let t=!1;return X(e,he(e)&&(A.current===e&&O>0||m(e)>0)).then(async n=>{if(!t){if(Z(e))try{let n=await _e(e);if(t)return;if(n){x(n),g(!1);return}}catch{}o(n),g(!1)}}).catch(async n=>{if(!t){if(Z(e))try{let n=await _e(e);if(t)return;if(n){x(n),g(!1);return}}catch{}y(n.message),g(!1)}}),()=>{t=!0}},[e,O]),(0,_.useEffect)(()=>{T(t??``)},[t]);let j=(0,_.useMemo)(()=>!t||!a?!1:!a.some(e=>e.id===t),[t,a]),M=(0,_.useCallback)(e=>{if(e===`__OTHER__`){C(!0),T(t??``);return}e!==`__CUSTOM__`&&n(e===`__DEFAULT__`?void 0:e)},[n,t]),N=(0,_.useCallback)(()=>{n(w.trim()||void 0),C(!1)},[w,n]);if(s)return(0,V.jsx)(`span`,{className:`muted small`,children:`loading models…`});if(b){let e=b.activeInstallsCount;return(0,V.jsx)(`span`,{className:`muted small`,children:e>0?`No models downloaded; ${e} download${e===1?``:`s`} in progress`:`No models downloaded`})}if(v)return(0,V.jsx)(`span`,{className:`error small`,title:v,children:`failed to load`});if(S)return(0,V.jsxs)(`span`,{className:`model-picker-other`,children:[(0,V.jsx)(`input`,{type:`text`,value:w,onChange:e=>T(e.target.value),placeholder:`Model ID`}),(0,V.jsx)(`button`,{type:`button`,onClick:N,children:`Save`}),(0,V.jsx)(`button`,{type:`button`,onClick:()=>{C(!1),T(t??``)},children:`Cancel`})]});let P=j?`__CUSTOM__`:t||`__DEFAULT__`,F=t?a?.find(e=>e.id===t):void 0,I=F&&F.supportsTools===!1,L=t&&(e===`llama-cpp`||e===`ds4`)?E?.get(`${e}:${t}`):void 0,R=L&&!L.stale&&L.record.status===`probed`?r({fitness:{record:L.record,stale:L.stale,hardwareChanged:L.hardwareChanged}}):null;return(0,V.jsxs)(`span`,{className:`model-picker-wrap`,children:[(0,V.jsxs)(c,{value:P,onValueChange:M,children:[(0,V.jsx)(d,{children:(0,V.jsx)(u,{placeholder:i})}),(0,V.jsxs)(f,{children:[(0,V.jsx)(l,{value:`__DEFAULT__`,children:i}),a?.map(e=>(0,V.jsxs)(l,{value:e.id,children:[e.name,e.supportsReasoning?` · reasoning`:``]},e.id)),j&&(0,V.jsxs)(l,{value:`__CUSTOM__`,children:[t,` (custom)`]}),(0,V.jsx)(l,{value:`__OTHER__`,children:`Other…`})]})]}),I&&(0,V.jsx)(`span`,{className:`model-picker-warn`,title:`This model doesn't support structured tool calls, so gezellen on it can't use MCP tools (read/write files, create tasks, etc.). Pick a tool-capable model (llama3.1+, qwen2.5+, mistral, gpt-oss, etc.) if you need tool use.`,children:`no tools`}),R?.tier===`warn`&&(0,V.jsxs)(`span`,{className:`model-picker-warn`,title:R.detail,children:[`fitness: `,R.label]})]})}function ye({provider:e,model:t,value:n,onChange:r}){let[i,a]=(0,_.useState)(q.get(e)??null);if((0,_.useEffect)(()=>{X(e).then(a).catch(()=>{})},[e]),!t||!i)return null;let o=i.find(e=>e.id===t);if(!o?.supportsReasoning)return null;let s=o.reasoningEfforts??[`low`,`medium`,`high`],p=o.defaultReasoningEffort?`Default (${o.defaultReasoningEffort})`:`Default`;return(0,V.jsxs)(c,{value:n||`__DEFAULT__`,onValueChange:e=>r(e===`__DEFAULT__`?void 0:e),children:[(0,V.jsx)(d,{"aria-label":`Reasoning effort`,children:(0,V.jsx)(u,{})}),(0,V.jsxs)(f,{children:[(0,V.jsx)(l,{value:`__DEFAULT__`,children:p}),s.map(e=>(0,V.jsx)(l,{value:e,children:e},e))]})]})}var be={minimal:`Minimal`,low:`Low`,medium:`Medium`,high:`High`,xhigh:`Extra high`,max:`Maximum`,ultra:`Ultra`};function xe({provider:e,model:t,defaultModel:n,value:r,onChange:i}){let[a,o]=(0,_.useState)(q.get(e)??null);if((0,_.useEffect)(()=>{let t=!1;return X(e).then(e=>{t||o(e)}).catch(()=>{}),()=>{t=!0}},[e]),!a)return(0,V.jsx)(`span`,{className:`muted small`,children:`loading effort levels…`});let s=a.find(e=>e.id===(t??n));if(!s?.supportsReasoning)return null;let c=s.reasoningEfforts??[`low`,`medium`,`high`];return(0,V.jsx)(`div`,{className:`gz-tray reasoning-effort-tray`,role:`radiogroup`,"aria-label":`Reasoning effort`,children:[[void 0,s.defaultReasoningEffort?`Model default (${be[s.defaultReasoningEffort]??s.defaultReasoningEffort})`:`Model default`],...c.map(e=>[e,be[e]??e])].map(([e,t])=>{let n=r===e||!r&&e===void 0;return(0,V.jsx)(`button`,{type:`button`,role:`radio`,"aria-checked":n,className:`gz-key${n?` gz-key-active`:``}`,onClick:()=>i(e),children:t},e??`__DEFAULT__`)})})}export{le as i,xe as n,ve as r,ye as t};
@@ -1 +1 @@
1
- import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{n as t,t as n}from"./jsx-runtime-CEpd2cAX.js";import{F as r,I as i,M as a,N as o,P as s,j as c,k as l}from"./primitives-DEsn1shf.js";import{t as u}from"./api-BX5xXiFs.js";import{o as d,t as f}from"./pending-drafts-YVW6X55O.js";var p=e(t(),1),m=n(),h=[{id:`post-message`,title:`Post a message when a phase starts`,blurb:`Writes a note onto the task so the team sees it.`,requires:[`tasks.write`]},{id:`fetch-and-summarize`,title:`Fetch a URL and summarize it`,blurb:`Pulls a page and produces a one-paragraph summary.`,requires:[`network`,`llm`]},{id:`check-files`,title:`Check files and decide`,blurb:`Inspects the workspace and outputs a yes/no a phase can advance on.`,requires:[`workspace.read`]},{id:`call-tool`,title:`Call a tool`,blurb:`Runs any registered tool — search, git, GitHub, browser.`,requires:[`network`]},{id:`ask-ai`,title:`Ask the AI about this task`,blurb:`Reads a task and answers a question about it.`,requires:[`llm`,`tasks.read`]},{id:`blank`,title:`Start blank`,blurb:`Just the skeleton every script needs.`,requires:[]}];function g(e){let t=e.toLowerCase().replace(/[^a-z0-9\s-]/g,``).split(/[\s-]+/).filter(Boolean).slice(0,4).join(`-`);return/^[a-z]/.test(t)?t:t?`do-${t}`:``}function _({open:e,projectId:t,scope:n,onClose:_,onCreated:v}){let[y,b]=(0,p.useState)(``),[x,S]=(0,p.useState)(!1),[C,w]=(0,p.useState)(``),[T,E]=(0,p.useState)(`blank`),[D,O]=(0,p.useState)(!1),[k,A]=(0,p.useState)(null);(0,p.useEffect)(()=>{e&&(b(``),S(!1),w(``),E(`blank`),O(!1),A(null))},[e]);let j=x||y?y:g(C),M=/^[a-zA-Z][\w-]*$/.test(j),N=async e=>{if(!(D||!M)){O(!0),A(null);try{let r={name:j,...C.trim()?{description:C.trim()}:{},template:e?`blank`:T};await(n===`user`?u.createUserScript(r):u.createProjectScript(t,r)),e&&C.trim()&&f(`${n?`${n}:`:``}${t}/${j}`,C.trim()),v(j)}catch(e){A(e.message)}finally{O(!1)}}};return(0,m.jsx)(r,{open:e,onOpenChange:e=>{!e&&!D&&_()},children:(0,m.jsxs)(s,{children:[(0,m.jsx)(o,{}),(0,m.jsxs)(c,{className:`new-script-dialog`,children:[(0,m.jsx)(i,{asChild:!0,children:(0,m.jsx)(`h3`,{children:`New script`})}),(0,m.jsxs)(a,{className:`muted small`,children:[`Scripts run automatically when task phases start or finish — or whenever you run them yourself.`,n===`user`&&` This one goes in the shared library, so every project can use it.`]}),(0,m.jsxs)(`div`,{className:`new-script-dialog__body`,children:[(0,m.jsxs)(`label`,{className:`new-script-field`,children:[(0,m.jsx)(`span`,{children:`Describe what it should do (optional)`}),(0,m.jsx)(`textarea`,{value:C,onChange:e=>w(e.target.value),placeholder:`When this phase starts, fetch the PR diff and post a one-paragraph summary…`,rows:3,disabled:D})]}),(0,m.jsxs)(`div`,{className:`new-script-ai`,children:[(0,m.jsx)(`button`,{type:`button`,className:`primary`,disabled:D||!C.trim()||!M,onClick:()=>void N(!0),children:`Draft it with AI`}),(0,m.jsx)(`span`,{className:`muted small`,children:`or pick a starting point:`})]}),(0,m.jsx)(`div`,{className:`new-script-templates`,"aria-label":`Starter template`,children:h.map(e=>(0,m.jsxs)(`button`,{type:`button`,"aria-pressed":T===e.id,className:`new-script-template${T===e.id?` active`:``}`,onClick:()=>E(e.id),disabled:D,children:[(0,m.jsx)(`strong`,{children:e.title}),(0,m.jsx)(`span`,{className:`muted small`,children:e.blurb}),(0,m.jsx)(d,{requires:e.requires})]},e.id))}),(0,m.jsxs)(`label`,{className:`new-script-field`,children:[(0,m.jsx)(`span`,{children:`Name`}),(0,m.jsx)(`input`,{type:`text`,value:j,onChange:e=>{b(e.target.value),S(!0)},placeholder:`summarize-and-post`,disabled:D}),j&&!M&&(0,m.jsx)(`span`,{className:`scripts-view__error small`,children:`Names start with a letter and use only letters, digits, dashes, underscores.`})]}),k&&(0,m.jsx)(`p`,{className:`scripts-view__error`,children:k})]}),(0,m.jsxs)(l,{children:[(0,m.jsx)(`button`,{type:`button`,onClick:_,disabled:D,children:`Cancel`}),(0,m.jsx)(`button`,{type:`button`,className:`primary`,disabled:D||!M,onClick:()=>void N(!1),children:D?`Creating…`:`Create`})]})]})]})})}export{_ as t};
1
+ import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{n as t,t as n}from"./jsx-runtime-CEpd2cAX.js";import{t as r}from"./api-BPraLwsh.js";import{G as i,H as a,J as o,K as s,W as c,Y as l,q as u}from"./primitives-CWrGZpPI.js";import{o as d,t as f}from"./pending-drafts-B11MKQ9R.js";var p=e(t(),1),m=n(),h=[{id:`post-message`,title:`Post a message when a phase starts`,blurb:`Writes a note onto the task so the team sees it.`,requires:[`tasks.write`]},{id:`fetch-and-summarize`,title:`Fetch a URL and summarize it`,blurb:`Pulls a page and produces a one-paragraph summary.`,requires:[`network`,`llm`]},{id:`check-files`,title:`Check files and decide`,blurb:`Inspects the workspace and outputs a yes/no a phase can advance on.`,requires:[`workspace.read`]},{id:`call-tool`,title:`Call a tool`,blurb:`Runs any registered tool — search, git, GitHub, browser.`,requires:[`network`]},{id:`ask-ai`,title:`Ask the AI about this task`,blurb:`Reads a task and answers a question about it.`,requires:[`llm`,`tasks.read`]},{id:`blank`,title:`Start blank`,blurb:`Just the skeleton every script needs.`,requires:[]}];function g(e){let t=e.toLowerCase().replace(/[^a-z0-9\s-]/g,``).split(/[\s-]+/).filter(Boolean).slice(0,4).join(`-`);return/^[a-z]/.test(t)?t:t?`do-${t}`:``}function _({open:e,projectId:t,scope:n,onClose:_,onCreated:v}){let[y,b]=(0,p.useState)(``),[x,S]=(0,p.useState)(!1),[C,w]=(0,p.useState)(``),[T,E]=(0,p.useState)(`blank`),[D,O]=(0,p.useState)(!1),[k,A]=(0,p.useState)(null);(0,p.useEffect)(()=>{e&&(b(``),S(!1),w(``),E(`blank`),O(!1),A(null))},[e]);let j=x||y?y:g(C),M=/^[a-zA-Z][\w-]*$/.test(j),N=async e=>{if(!(D||!M)){O(!0),A(null);try{let i={name:j,...C.trim()?{description:C.trim()}:{},template:e?`blank`:T};await(n===`user`?r.createUserScript(i):r.createProjectScript(t,i)),e&&C.trim()&&f(`${n?`${n}:`:``}${t}/${j}`,C.trim()),v(j)}catch(e){A(e.message)}finally{O(!1)}}};return(0,m.jsx)(o,{open:e,onOpenChange:e=>{!e&&!D&&_()},children:(0,m.jsxs)(u,{children:[(0,m.jsx)(s,{}),(0,m.jsxs)(c,{className:`new-script-dialog`,children:[(0,m.jsx)(l,{asChild:!0,children:(0,m.jsx)(`h3`,{children:`New script`})}),(0,m.jsxs)(i,{className:`muted small`,children:[`Scripts run automatically when task phases start or finish — or whenever you run them yourself.`,n===`user`&&` This one goes in the shared library, so every project can use it.`]}),(0,m.jsxs)(`div`,{className:`new-script-dialog__body`,children:[(0,m.jsxs)(`label`,{className:`new-script-field`,children:[(0,m.jsx)(`span`,{children:`Describe what it should do (optional)`}),(0,m.jsx)(`textarea`,{value:C,onChange:e=>w(e.target.value),placeholder:`When this phase starts, fetch the PR diff and post a one-paragraph summary…`,rows:3,disabled:D})]}),(0,m.jsxs)(`div`,{className:`new-script-ai`,children:[(0,m.jsx)(`button`,{type:`button`,className:`primary`,disabled:D||!C.trim()||!M,onClick:()=>void N(!0),children:`Draft it with AI`}),(0,m.jsx)(`span`,{className:`muted small`,children:`or pick a starting point:`})]}),(0,m.jsx)(`div`,{className:`new-script-templates`,"aria-label":`Starter template`,children:h.map(e=>(0,m.jsxs)(`button`,{type:`button`,"aria-pressed":T===e.id,className:`new-script-template${T===e.id?` active`:``}`,onClick:()=>E(e.id),disabled:D,children:[(0,m.jsx)(`strong`,{children:e.title}),(0,m.jsx)(`span`,{className:`muted small`,children:e.blurb}),(0,m.jsx)(d,{requires:e.requires})]},e.id))}),(0,m.jsxs)(`label`,{className:`new-script-field`,children:[(0,m.jsx)(`span`,{children:`Name`}),(0,m.jsx)(`input`,{type:`text`,value:j,onChange:e=>{b(e.target.value),S(!0)},placeholder:`summarize-and-post`,disabled:D}),j&&!M&&(0,m.jsx)(`span`,{className:`scripts-view__error small`,children:`Names start with a letter and use only letters, digits, dashes, underscores.`})]}),k&&(0,m.jsx)(`p`,{className:`scripts-view__error`,children:k})]}),(0,m.jsxs)(a,{children:[(0,m.jsx)(`button`,{type:`button`,onClick:_,disabled:D,children:`Cancel`}),(0,m.jsx)(`button`,{type:`button`,className:`primary`,disabled:D||!M,onClick:()=>void N(!1),children:D?`Creating…`:`Create`})]})]})]})})}export{_ as t};
@@ -0,0 +1,2 @@
1
+ import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{n as t,t as n}from"./jsx-runtime-CEpd2cAX.js";import{Bt as r,yn as i}from"./dist-BqGwkOe5.js";import{t as a}from"./dist-BaHut5iX.js";import{t as o}from"./api-BPraLwsh.js";import{H as ee,J as te,K as ne,W as re,Y as ie,d as ae,l as s,m as c,p as oe,q as se,s as ce}from"./primitives-CWrGZpPI.js";import{t as le}from"./GezelJsonEditor-7vDGyBib.js";import{r as l}from"./new-project-meta-_f9sfcRX.js";import{$ as ue,Q as u,Z as de,at as fe,et as pe,it as me,nt as he,ot as ge,rt as _e,tt as ve}from"./index-C0DYtvfg.js";import{t as ye}from"./CraftbookToolsetSetup-BKg136L1.js";import{t as be}from"./useShowWorkInProgressFeatures-BhDNuQiU.js";var d=e(t(),1);function xe(e){if(e instanceof a){let t=e.details;if(t&&typeof t==`object`&&`error`in t){let e=t.error;if(typeof e==`string`&&e.length>0&&e!==`internal_error`)return e}return e.message}return e instanceof Error?e.message:String(e)}var f=n(),p=`__auto`,Se={"one-time":{title:`New Task`,subtitle:`Pick a craftbook — a proven recipe your crew follows step by step — or start blank.`,generalLabel:u.label,generalDescription:u.description,featuredLabel:`Recommended`,featuredTitle:`Recommended`,featuredTagline:`proven recipes for this kind of project`,submitLabel:`Create task`,footnote:`Lands ready to fire — nothing runs until you fire it.`},scheduled:{title:`New Scheduled Task`,subtitle:`Choose a repeatable craftbook, then set when each fresh run should begin.`,generalLabel:`Blank scheduled task`,generalDescription:`Define a repeatable job from scratch and run a fresh copy on a cadence.`,featuredLabel:`For schedules`,featuredTitle:`Scheduled craftbooks`,featuredTagline:`recipes identified as safe for recurring unattended runs`,submitLabel:`Create schedule`,footnote:`Starts active and creates a fresh task on each scheduled run.`},"night-shift":{title:`New Night Shift Task`,subtitle:`Choose work your crew can pick up unattended during the Night Shift window.`,generalLabel:`Blank Night Shift task`,generalDescription:`Define a one-off job that waits for Night Shift before it begins.`,featuredLabel:`For Night Shift`,featuredTitle:`Night Shift craftbooks`,featuredTagline:`recipes identified as safe for unattended overnight work`,submitLabel:`Queue for Night Shift`,footnote:`Starts active, but only runs while Night Shift is on.`}};function m({open:e,creationMode:t=`one-time`,defaultProjectId:n,projects:a,gezels:m,projectLocked:Te,onClose:h,onCreated:g}){let _=Se[t],Ee=be(),[v,De]=(0,d.useState)(n),[y,Oe]=(0,d.useState)([]),[ke,b]=(0,d.useState)(!1),x=(0,d.useRef)(0),[S,Ae]=(0,d.useState)({}),[C,je]=(0,d.useState)(null),[w,Me]=(0,d.useState)(new Set),[T,E]=(0,d.useState)(null),[D,O]=(0,d.useState)(`pick`),[Ne,k]=(0,d.useState)(!1),[A,Pe]=(0,d.useState)(``),[j,M]=(0,d.useState)(`all`),[Fe,Ie]=(0,d.useState)(!1),[N,P]=(0,d.useState)(``),[F,Le]=(0,d.useState)(!1),[I,Re]=(0,d.useState)(``),[ze,Be]=(0,d.useState)(`Main`),[Ve,He]=(0,d.useState)(``),[Ue,We]=(0,d.useState)(!1),[L,R]=(0,d.useState)({}),[z,Ge]=(0,d.useState)(``),[B,Ke]=(0,d.useState)(`skip`),[V,H]=(0,d.useState)(!1),[qe,U]=(0,d.useState)(``),[Je,W]=(0,d.useState)(null),Ye=(0,d.useRef)(0);(0,d.useEffect)(()=>{e&&(De(n),E(null),k(!1),O(`pick`),Pe(``),M(`all`),Ie(!1),P(``),Le(!1),Re(``),Be(`Main`),He(``),We(!1),R({}),Ge(``),Ke(`skip`),H(!1),U(``),W(null))},[e,n]);let Xe=(0,d.useCallback)(async()=>{let e=++x.current;if(!v){if(e!==x.current)return;Oe([]),b(!0);return}try{let t=await o.listProjectCraftbooks(v);if(e!==x.current)return;let n=i(t.items??[],Ee),r=new Set(n.map(e=>e.manifest.id));Oe(ge(n)),Ae(t.missingToolsets??{}),je(t.projectType??null),Me(new Set((t.suggestedIds??[]).filter(e=>r.has(e)))),E(e=>e&&!r.has(e)?null:e)}catch{if(e!==x.current)return;Oe([]),Ae({}),je(null),Me(new Set)}finally{e===x.current&&b(!0)}},[v,Ee]);(0,d.useEffect)(()=>{e&&(b(!1),Xe())},[e,Xe]),(0,d.useEffect)(()=>{!e||!ke||Fe||(Ie(!0),(t===`one-time`?w.size>0:y.some(e=>t===`scheduled`?e.manifest.runModes?.scheduled:e.manifest.runModes?.nightShift))&&M(`recommended`))},[e,ke,Fe,w,t,y]);let G=T?y.find(e=>e.manifest.id===T)??null:null,K=(()=>{if(!G)return null;let e=G.manifest;return(e.steps.find(t=>t.id===e.entryStepId)??e.steps[0])?.suggestedRole??null})(),Ze=t!==`scheduled`&&(G?.manifest.connectors??[]).some(e=>e.typeId===`github-pulls`&&!e.optional),Qe=String(L.number??``).trim();(0,d.useEffect)(()=>{let t=++Ye.current;W(null),!(!e||!Ze||!v)&&(async()=>{try{let[e,n]=await Promise.all([o.getProjectGitStatus(v),o.listProjectGitHubPulls(v)]);if(t!==Ye.current)return;let{matchingCount:i}=r(n.pulls??[],e.branch);if(i>0)return;W(e.branch?`No open pull request for branch "${e.branch}" — enter a pull request number above, or switch branches first.`:`This checkout is not on a branch — enter a pull request number above.`)}catch{}})()},[e,Ze,v]);let $e=(0,d.useCallback)(()=>{E(null),k(!0),R({}),U(``),O(`configure`),F||P(``)},[F]),et=(0,d.useCallback)(()=>{O(`pick`),U(``)},[]),tt=(0,d.useCallback)(e=>{De(e),E(null),k(!1),R({}),M(`all`),Ie(!1),U(``)},[]),nt=(0,d.useCallback)(e=>{if(E(e.manifest.id),k(!1),R(he(e.manifest.paramSchema)),U(``),O(`configure`),F||P(e.manifest.name),!Ue){let t=e.manifest.defaultAssignee;t?.kind===`gezel`&&m.some(e=>e.id===t.gezelId)&&He(t.gezelId)}},[F,Ue,m]),q=Ve||(K?p:m[0]?.id??`__user`),J=q===p?null:q===`__user`?{kind:`user`}:{kind:`gezel`,gezelId:q},Y=(0,d.useMemo)(()=>fe(y),[y]),X=A.trim().toLowerCase(),Z=X.length>0,Q=(0,d.useMemo)(()=>{if(t===`one-time`)return y.filter(e=>w.has(e.manifest.id));let e=t===`scheduled`?`scheduled`:`nightShift`;return y.filter(t=>t.manifest.runModes?.[e]).sort((t,n)=>{let r=+(t.manifest.runModes?.[e]===`recommended`);return+(n.manifest.runModes?.[e]===`recommended`)-r||t.manifest.name.localeCompare(n.manifest.name)})},[y,w,t]),rt=(0,d.useCallback)(e=>{if(t===`one-time`)return w.has(e.manifest.id);let n=t===`scheduled`?`scheduled`:`nightShift`;return e.manifest.runModes?.[n]===`recommended`},[t,w]),it=(0,d.useMemo)(()=>Z?y.filter(e=>`${e.manifest.id} ${e.manifest.name} ${e.manifest.description} ${(e.manifest.tags??[]).join(` `)}`.toLowerCase().includes(X)).sort((e,t)=>{let n=w.has(e.manifest.id)||e.manifest.tags?.includes(`recommended`)?1:0;return(w.has(t.manifest.id)||t.manifest.tags?.includes(`recommended`)?1:0)-n||Ce(e,X)-Ce(t,X)||e.manifest.name.localeCompare(t.manifest.name)}):y,[y,Z,X,w]),at=!Z||`${_.generalLabel} ${_.generalDescription} blank fresh`.toLowerCase().includes(X),ot=(0,d.useMemo)(()=>{if(Z)return[{id:`search`,title:`Craftbooks`,tagline:`matching "${A.trim()}"`,books:it}];if(j===`recommended`&&Q.length>0)return[{id:`recommended`,title:t===`one-time`&&C?`Recommended for ${C.label}`:_.featuredTitle,tagline:_.featuredTagline,books:Q}];let e=Y.find(e=>e.id===j);return e?[{id:e.id,title:e.label,tagline:e.tagline,books:y.filter(t=>e.bookIds.has(t.manifest.id))}]:[{id:`all`,title:`All craftbooks`,tagline:void 0,books:y}]},[Z,A,it,j,Q,C,Y,y,t,_]),$=G?S[G.manifest.id]??[]:[],st=(0,d.useCallback)(async e=>{if(e.preventDefault(),V||D!==`configure`)return;if(U(``),!v){U(`Pick a project.`);return}let n=z.trim();if(t===`scheduled`&&!n){U(`Enter a schedule.`);return}if(G){let e=G.manifest;if((S[e.id]?.length??0)>0){U(`This craftbook needs its toolsets installed first — see the setup list.`);return}let r=e.paramSchema,i=(Array.isArray(r?.required)?r.required:[]).find(e=>{let t=L[e];return t==null||t===``});if(i){U(`"${i}" is required.`);return}let a=_e(L);H(!0);try{let r=t===`scheduled`?await o.createTask(v,{title:N.trim()||e.name,description:`Recurring scheduled task. ${ue(e,a)} Each scheduled run creates a fresh task from this recipe.`,steps:[{name:`Wait for schedule`,prompt:`This host holds a recurring schedule. It does not perform the work itself; each tick creates a fresh child task.`}],spawnsCraftbookId:e.id,...G.item.sourceId?{spawnsCraftbookSourceId:G.item.sourceId}:{},...J?{assignee:J}:{},cron:{expression:n,overlap:B},...Object.keys(a).length>0?{spawnsCraftbookParams:a}:{}}):await o.createTask(v,{title:N.trim()||e.name,description:ue(e,a),craftbookId:e.id,...G.item.sourceId?{craftbookSourceId:G.item.sourceId}:{},...J?{assignee:J}:{},...t===`one-time`?{dispatchEntry:!0}:{nightShift:{enabled:!0},dispatchEntry:!0},...Object.keys(a).length>0?{craftbookParams:a}:{}});if(t!==`scheduled`&&Object.keys(a).length>0&&r.activeStepId){let e=[`# Invocation parameters`,``];for(let[t,n]of Object.entries(a))e.push(`- **${t}**: ${n}`);await o.appendTaskNote(r.projectId,r.num,{text:e.join(`
2
+ `),stepId:r.activeStepId}).catch(()=>{})}await g(r),h()}catch(e){U(xe(e))}finally{H(!1)}return}let r=N.trim();if(!r){U(`Title is required.`);return}if(I.trim().length<40){U(`Description must be at least 40 characters — the job-to-be-done from the user's perspective. What does success look like?`);return}let i=ze.split(/\n|,/).map(e=>e.trim()).filter(Boolean).map(e=>({name:e}));i.length===0&&i.push({name:`Main`}),H(!0);try{await g(t===`scheduled`?await o.createTask(v,{title:r,description:I.trim(),steps:[{name:`Wait for schedule`,prompt:`This host holds a recurring schedule. It does not perform the work itself; each tick creates a fresh child task.`}],spawnsSteps:i,...J?{assignee:J}:{},cron:{expression:n,overlap:B}}):await o.createTask(v,{title:r,description:I.trim(),steps:i,...J?{assignee:J}:{},...t===`one-time`?{status:`draft`}:{nightShift:{enabled:!0},dispatchEntry:!0}})),h()}catch(e){U(xe(e))}finally{H(!1)}},[V,D,t,v,G,S,L,N,J,I,ze,z,B,g,h]),ct=G&&ve(G.manifest)?G.manifest.paramSchema:null,lt=V||G!==null&&$.length>0,ut=G?`Craftbook${rt(G)?t===`night-shift`?` · recommended for Night Shift`:t===`scheduled`?` · recommended for schedules`:` · recommended`:``}`:t===`one-time`?`Blank task`:t===`scheduled`?`Blank schedule`:`Blank Night Shift task`,dt=a.find(e=>e.id===v)?.name??``;return(0,f.jsx)(te,{open:e,onOpenChange:e=>{e||h()},children:(0,f.jsxs)(se,{children:[(0,f.jsx)(ne,{}),(0,f.jsx)(re,{className:`gz-npd gz-ntd gz-npd-step-${D}`,children:(0,f.jsx)(`form`,{onSubmit:st,style:{display:`contents`},children:D===`pick`?(0,f.jsxs)(f.Fragment,{children:[(0,f.jsxs)(`header`,{className:`gz-npd-header`,children:[(0,f.jsxs)(`div`,{className:`gz-npd-header-copy`,children:[(0,f.jsx)(ie,{asChild:!0,children:(0,f.jsx)(`h3`,{children:_.title})}),(0,f.jsx)(`p`,{className:`gz-npd-header-sub`,children:_.subtitle})]}),(0,f.jsxs)(`div`,{className:`gz-ntd-header-controls`,children:[!Te&&(0,f.jsxs)(`label`,{className:`gz-ntd-header-project`,children:[(0,f.jsx)(`span`,{children:`Project`}),(0,f.jsxs)(ae,{value:v,onValueChange:tt,children:[(0,f.jsx)(oe,{children:(0,f.jsx)(c,{})}),(0,f.jsx)(ce,{children:a.map(e=>(0,f.jsx)(s,{value:e.id,children:e.name},e.id))})]})]}),(0,f.jsxs)(`label`,{className:`gz-npd-search`,children:[(0,f.jsx)(`span`,{className:`sr-only`,children:`Search craftbooks`}),(0,f.jsx)(`input`,{type:`search`,value:A,onChange:e=>Pe(e.target.value),placeholder:`Search craftbooks…`})]})]})]}),(0,f.jsxs)(`div`,{className:`gz-npd-body`,children:[(0,f.jsxs)(`nav`,{className:`gz-npd-rail`,"aria-label":`Craftbook shelves`,children:[Q.length>0&&(0,f.jsxs)(`button`,{type:`button`,className:`gz-npd-rail-item${!Z&&j===`recommended`?` active`:``}`,onClick:()=>M(`recommended`),children:[(0,f.jsx)(l,{glyph:`sprout`,size:16}),(0,f.jsx)(`span`,{className:`gz-npd-rail-label`,children:_.featuredLabel}),(0,f.jsx)(`span`,{className:`gz-npd-rail-count`,children:Q.length})]}),(0,f.jsxs)(`button`,{type:`button`,className:`gz-npd-rail-item${!Z&&j===`all`?` active`:``}`,onClick:()=>M(`all`),children:[(0,f.jsx)(l,{glyph:`sheet`,size:16}),(0,f.jsx)(`span`,{className:`gz-npd-rail-label`,children:`All craftbooks`}),(0,f.jsx)(`span`,{className:`gz-npd-rail-count`,children:y.length})]}),Y.map((e,t)=>{let n=Y[t-1]?.family===e.family?null:me(e.family);return(0,f.jsxs)(d.Fragment,{children:[n&&(0,f.jsx)(`span`,{className:`gz-npd-rail-group`,children:n}),(0,f.jsxs)(`button`,{type:`button`,className:`gz-npd-rail-item${!Z&&j===e.id?` active`:``}`,onClick:()=>M(e.id),children:[(0,f.jsx)(l,{glyph:e.glyph,size:16}),(0,f.jsx)(`span`,{className:`gz-npd-rail-label`,children:e.label}),(0,f.jsx)(`span`,{className:`gz-npd-rail-count`,children:e.bookIds.size})]})]},e.id)})]}),(0,f.jsxs)(`div`,{className:`gz-npd-gallery`,role:`radiogroup`,"aria-label":`Task type`,children:[at&&(0,f.jsxs)(`section`,{className:`gz-npd-section`,children:[(0,f.jsx)(`div`,{className:`gz-npd-section-head`,children:(0,f.jsx)(`span`,{className:`gz-npd-section-title`,children:`Start fresh`})}),(0,f.jsx)(`div`,{className:`gz-npd-grid`,children:(0,f.jsx)(we,{label:_.generalLabel,description:_.generalDescription,glyph:u.glyph,index:0,active:Ne,onSelect:$e})})]}),ot.map(e=>(0,f.jsxs)(`section`,{className:`gz-npd-section`,children:[(0,f.jsxs)(`div`,{className:`gz-npd-section-head`,children:[(0,f.jsx)(`span`,{className:`gz-npd-section-title`,children:e.title}),e.tagline&&(0,f.jsx)(`span`,{className:`gz-npd-section-tagline`,children:e.tagline})]}),e.books.length>0?(0,f.jsx)(`div`,{className:`gz-npd-grid`,children:e.books.map((e,t)=>(0,f.jsx)(we,{label:e.manifest.name,description:e.manifest.description,glyph:pe(e.manifest),...e.item.iconSvg?{iconSvg:e.item.iconSvg}:{},...e.item.logoUrl?{logoUrl:e.item.logoUrl}:{},suggested:rt(e),index:t+1,active:e.manifest.id===T,onSelect:()=>nt(e)},e.manifest.id))}):(0,f.jsx)(`p`,{className:`gz-npd-empty`,children:ke?Z?`No craftbooks match your search.`:`No craftbooks here yet.`:`Loading craftbooks…`}),e.id===`recommended`&&y.length>Q.length&&(0,f.jsxs)(`button`,{type:`button`,className:`gz-ntd-show-all`,onClick:()=>M(`all`),children:[`Browse all `,y.length,` craftbooks`]})]},e.id))]})]}),(0,f.jsxs)(`div`,{className:`gz-npd-pane-footer gz-npd-pick-footer`,children:[(0,f.jsx)(`p`,{className:`gz-npd-footnote`,children:`Pick one to see what it does — nothing is created until the next screen.`}),(0,f.jsx)(ee,{children:(0,f.jsx)(`button`,{type:`button`,onClick:h,children:`Cancel`})})]})]}):(0,f.jsxs)(f.Fragment,{children:[(0,f.jsxs)(`header`,{className:`gz-npd-header gz-npd-detail-header`,children:[(0,f.jsxs)(`button`,{type:`button`,className:`gz-npd-back`,onClick:et,children:[(0,f.jsx)(`span`,{"aria-hidden":`true`,children:`‹`}),G?`Craftbooks`:`Back`]}),(0,f.jsxs)(`div`,{className:`gz-npd-detail-id`,children:[(0,f.jsx)(`span`,{className:`gz-npd-detail-art`,"aria-hidden":`true`,children:G?(0,f.jsx)(de,{...G.item.iconSvg?{iconSvg:G.item.iconSvg}:{},...G.item.logoUrl?{logoUrl:G.item.logoUrl}:{},svgClassName:`gz-npd-hero-art-svg`,fallback:(0,f.jsx)(l,{glyph:pe(G.manifest),size:26})}):(0,f.jsx)(l,{glyph:u.glyph,size:26})}),(0,f.jsxs)(`div`,{className:`gz-npd-header-copy`,children:[(0,f.jsx)(`p`,{className:`gz-npd-hero-eyebrow`,children:ut}),(0,f.jsx)(ie,{asChild:!0,children:(0,f.jsx)(`h3`,{className:`gz-npd-hero-name`,children:G?G.manifest.name:_.generalLabel})})]})]}),!Te&&dt&&(0,f.jsxs)(`p`,{className:`gz-ntd-detail-project`,children:[`in `,(0,f.jsx)(`strong`,{children:dt})]})]}),(0,f.jsxs)(`div`,{className:`gz-npd-detail`,"data-blank":G?void 0:`true`,children:[G&&(0,f.jsxs)(`div`,{className:`gz-npd-brief`,children:[(0,f.jsx)(`p`,{className:`gz-npd-brief-lede`,children:G.manifest.description}),G.manifest.basedOn&&(0,f.jsxs)(`p`,{className:`gz-ntd-based-on`,children:[`Based on`,` `,(0,f.jsx)(`a`,{href:G.manifest.basedOn.url,target:`_blank`,rel:`noreferrer`,children:G.manifest.basedOn.name})]}),(0,f.jsxs)(`div`,{className:`gz-ntd-steps`,children:[(0,f.jsxs)(`p`,{className:`gz-npd-give-eyebrow`,children:[G.manifest.steps.length,` step`,G.manifest.steps.length===1?``:`s`]}),(0,f.jsx)(`ol`,{className:`gz-ntd-steps-list`,children:G.manifest.steps.map(e=>(0,f.jsxs)(`li`,{children:[(0,f.jsxs)(`span`,{className:`gz-ntd-step-head`,children:[(0,f.jsx)(`span`,{className:`gz-ntd-step-name`,children:e.name}),e.suggestedRole&&(0,f.jsx)(`span`,{className:`gz-ntd-step-role`,children:e.suggestedRole})]}),e.description&&(0,f.jsx)(`span`,{className:`gz-ntd-step-note`,children:e.description})]},e.id))})]})]}),(0,f.jsxs)(`div`,{className:`gz-npd-setup`,children:[!G&&(0,f.jsx)(`p`,{className:`gz-npd-brief-lede`,children:_.generalDescription}),(0,f.jsxs)(`div`,{className:`gz-npd-pane-form`,children:[(0,f.jsxs)(`label`,{children:[`Title`,(0,f.jsx)(`input`,{value:N,onChange:e=>{P(e.target.value),Le(!0)},placeholder:G?G.manifest.name:`e.g. Ship the landing page`})]}),$.length>0&&G&&(0,f.jsxs)(`div`,{className:`gz-ntd-needs`,children:[(0,f.jsx)(`p`,{className:`gz-npd-give-eyebrow`,children:`Needs setup`}),(0,f.jsx)(ye,{missing:$,onAllInstalled:()=>void Xe(),onCancel:et})]}),ct&&$.length===0&&(0,f.jsxs)(`div`,{className:`gz-npd-params`,children:[(0,f.jsx)(`p`,{className:`gz-npd-give-eyebrow`,children:`Parameters`}),(0,f.jsx)(le,{schema:ct,value:L,onChange:e=>{R(e??{}),U(``)},density:`comfortable`})]}),!G&&(0,f.jsxs)(f.Fragment,{children:[(0,f.jsxs)(`label`,{children:[`Description `,(0,f.jsx)(`span`,{className:`muted`,children:`· a sentence or two`}),(0,f.jsx)(`textarea`,{value:I,onChange:e=>Re(e.target.value),rows:4,placeholder:`What's the problem? What does success look like for the user?`})]}),(0,f.jsxs)(`label`,{children:[`Steps `,(0,f.jsx)(`span`,{className:`muted`,children:`(one per line)`}),(0,f.jsx)(`textarea`,{value:ze,onChange:e=>Be(e.target.value),rows:4})]})]}),(0,f.jsxs)(`label`,{children:[`Assign to`,(0,f.jsxs)(ae,{value:q,onValueChange:e=>{He(e),We(!0)},children:[(0,f.jsx)(oe,{children:(0,f.jsx)(c,{})}),(0,f.jsxs)(ce,{children:[K&&(0,f.jsxs)(s,{value:p,children:[`Auto — the `,K,` for step 1`]}),m.map(e=>(0,f.jsxs)(s,{value:e.id,children:[e.name,e.role?` — ${e.role}`:``]},e.id)),(0,f.jsx)(s,{value:`__user`,children:`Me (no gezel)`})]})]}),q===p?(0,f.jsxs)(`small`,{className:`muted`,children:[`Every step picks its own specialist by role when the task fires. Step 1 goes to the `,K,`, and whoever that turns out to be owns the task.`]}):G&&(0,f.jsx)(`small`,{className:`muted`,children:`Steps that name a role pick their own specialist when the task fires — this only covers steps that name none.`}),q===`__user`&&(0,f.jsx)(`small`,{className:`muted`,children:`Assigned to you — firing won't hand it to a gezel.`})]}),t===`scheduled`&&(0,f.jsxs)(`div`,{className:`gz-ntd-schedule`,children:[(0,f.jsx)(`p`,{className:`gz-npd-give-eyebrow`,children:`Schedule`}),(0,f.jsxs)(`label`,{children:[`Cron expression `,(0,f.jsx)(`span`,{className:`muted`,children:`(UTC, 5-field)`}),(0,f.jsx)(`input`,{value:z,placeholder:`e.g. 0 9 * * 1 — every Monday 09:00`,onChange:e=>Ge(e.target.value)})]}),(0,f.jsxs)(`label`,{children:[`Overlap policy`,(0,f.jsxs)(ae,{value:B,onValueChange:e=>Ke(e),children:[(0,f.jsx)(oe,{children:(0,f.jsx)(c,{})}),(0,f.jsxs)(ce,{children:[(0,f.jsx)(s,{value:`skip`,children:`skip — don't spawn if a prior run is still active`}),(0,f.jsx)(s,{value:`queue`,children:`queue — always spawn, let the runner throttle`}),(0,f.jsx)(s,{value:`concurrent`,children:`concurrent — spawn unconditionally`})]})]})]})]})]})]})]},T??`__general`),(0,f.jsxs)(`div`,{className:`gz-npd-pane-footer gz-npd-detail-footer`,children:[qe?(0,f.jsx)(`p`,{className:`error small gz-npd-submit-error`,role:`alert`,children:qe}):Je&&!Qe?(0,f.jsx)(`p`,{className:`gz-npd-footnote gz-ntd-launch-hint`,children:Je}):(0,f.jsx)(`p`,{className:`gz-npd-footnote`,children:t===`one-time`&&G?`Starts immediately — the first gezel gets to work as soon as you create it.`:_.footnote}),(0,f.jsxs)(ee,{children:[(0,f.jsx)(`button`,{type:`button`,onClick:h,disabled:V,children:`Cancel`}),(0,f.jsx)(`button`,{type:`submit`,className:`primary`,disabled:lt,children:V?t===`one-time`&&G?`Starting…`:`Creating…`:t===`one-time`&&G?`Create & start`:_.submitLabel})]})]})]})})})]})})}function Ce(e,t){let n=e.manifest.name.toLowerCase();return n===t?0:n.startsWith(t)?1:n.split(/\s+/).some(e=>e.startsWith(t))?2:n.includes(t)?3:`${e.manifest.id} ${(e.manifest.tags??[]).join(` `)}`.toLowerCase().includes(t)?4:5}function we({label:e,description:t,active:n,iconSvg:r,logoUrl:i,glyph:a,suggested:o=!1,index:ee,onSelect:te}){return(0,f.jsxs)(`button`,{type:`button`,role:`radio`,"aria-checked":n,"aria-label":e,className:`gz-npd-card${n?` active`:``}${o?` gz-ntd-card-suggested`:``}`,onClick:te,style:{"--card-i":Math.min(ee,11)},children:[(0,f.jsx)(`span`,{className:`gz-npd-card-mark`,"aria-hidden":`true`,children:(0,f.jsx)(de,{...r?{iconSvg:r}:{},...i?{logoUrl:i}:{},svgClassName:`gz-npd-card-mark-svg`,fallback:(0,f.jsx)(l,{glyph:a,size:22})})}),(0,f.jsx)(`span`,{className:`gz-npd-card-name`,children:e}),(0,f.jsx)(`span`,{className:`gz-npd-card-description`,children:t})]})}export{m as t};