@bendyline/gezel-service 1.1.1 → 1.1.2

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 (185) hide show
  1. package/dist/NOTICE.md +3 -3
  2. package/dist/bin/gezeld.js +8471 -5311
  3. package/dist/handboek-content/technical/building-connected-apps-with-gezel-app-sdk.md +78 -0
  4. package/dist/handboek-content/whats-new/{1.26250.md → 1.26251.md} +5 -5
  5. package/dist/index-store/static-index-worker.js +160 -51
  6. package/dist/index.d.ts +416 -71
  7. package/dist/index.js +8465 -5305
  8. package/dist/memory/embed-worker.js +132 -4
  9. package/dist/memory/image-embed-worker.js +14 -5
  10. package/dist/providers/mlx/python/cache_persist.py +52 -8
  11. package/dist/providers/mlx/python/gezel_mlx_server.py +44 -1
  12. package/dist/providers/mlx/python/qwen4_ple.py +159 -0
  13. package/dist/providers/mlx/python/spec_decode.py +73 -31
  14. package/dist/providers/mlx/python/tool_call_stream.py +10 -2
  15. package/dist/providers/mlx/python/tool_grammar.py +16 -0
  16. package/dist/ui/assets/{AmbientDashboardCard-DcVHxEdC.js → AmbientDashboardCard-_xnAQGnk.js} +1 -1
  17. package/dist/ui/assets/{AudioEngineSettings-BFM2S1mm.js → AudioEngineSettings-CgXgbX0i.js} +1 -1
  18. package/dist/ui/assets/{BenchmarksView-84-YeULA.js → BenchmarksView-BlExZpYA.js} +1 -1
  19. package/dist/ui/assets/CatalogBrowser-DYXUZQ_t.js +1 -0
  20. package/dist/ui/assets/{ChannelsSettings-7NAVUk4k.js → ChannelsSettings-EH27HcqZ.js} +1 -1
  21. package/dist/ui/assets/ChatTimelineView-Dn1TNyVn.js +7 -0
  22. package/dist/ui/assets/{ConnectedAppsPanel-CIgF4Q3R.js → ConnectedAppsPanel-BROry-Y0.js} +1 -1
  23. package/dist/ui/assets/CraftbookEditor-B2RNJnFf.js +1 -0
  24. package/dist/ui/assets/{CraftbookScriptEditorView-Ck5tzj3Y.js → CraftbookScriptEditorView-B-vySmHP.js} +1 -1
  25. package/dist/ui/assets/{CraftbookTabContent-BWg7FhK_.js → CraftbookTabContent-BW_2KC89.js} +1 -1
  26. package/dist/ui/assets/{CraftbookToolsetSetup-EuFOiUzR.js → CraftbookToolsetSetup-J7rEa835.js} +1 -1
  27. package/dist/ui/assets/{CraftbooksView-BIzQ1VVn.js → CraftbooksView-BjBUWPGF.js} +1 -1
  28. package/dist/ui/assets/DiffpackReviewView-CD4qJmgT.js +1 -0
  29. package/dist/ui/assets/DocumentDetail-SYozruTJ.js +1 -0
  30. package/dist/ui/assets/DocumentsView-DE7eL49Z.js +1 -0
  31. package/dist/ui/assets/{Ds4Settings-9soZCSeO.js → Ds4Settings-DGzc7JcD.js} +1 -1
  32. package/dist/ui/assets/{EmbeddedChat-Cce7nxXT.js → EmbeddedChat-D92TaJQ8.js} +1 -1
  33. package/dist/ui/assets/{FaceRecognitionCard-BVZyOwB8.js → FaceRecognitionCard-CB1Dt9X4.js} +1 -1
  34. package/dist/ui/assets/FileMapView-kVBG22FU.js +1 -0
  35. package/dist/ui/assets/FoldersSettings-BWFQU5B4.js +1 -0
  36. package/dist/ui/assets/GezelDetail-Br4v42Nv.js +1 -0
  37. package/dist/ui/assets/{GezelJsonEditor-DXXt165-.js → GezelJsonEditor-B9XEiW5Y.js} +1 -1
  38. package/dist/ui/assets/GezellenView-DheEBAy4.js +1 -0
  39. package/dist/ui/assets/{GildeUpdatesCard-CtY8mUTA.js → GildeUpdatesCard-BeIYv09f.js} +1 -1
  40. package/dist/ui/assets/{GithubSignInChip-DT3l6E0Q.js → GithubSignInChip-eEGCe9ar.js} +1 -1
  41. package/dist/ui/assets/{HandboekMediaProvider-ByJ4NAzz.js → HandboekMediaProvider-D0zcbbpf.js} +1 -1
  42. package/dist/ui/assets/HandboekView-p0BZT1rH.js +1 -0
  43. package/dist/ui/assets/{HistoryView-CkinzFEC.js → HistoryView-CKWcWW-Y.js} +1 -1
  44. package/dist/ui/assets/{HomeView-DNBrQnwy.js → HomeView-b_TT5oV3.js} +1 -1
  45. package/dist/ui/assets/{ImageEngineSettings-BfM9HSd_.js → ImageEngineSettings-CJfk4OJ4.js} +1 -1
  46. package/dist/ui/assets/{ImageRecognitionSettings-CaSQu5Br.js → ImageRecognitionSettings-DzbvZk5S.js} +1 -1
  47. package/dist/ui/assets/{IncompleteDownloads-C36lTCMG.js → IncompleteDownloads-C8_XyP8O.js} +1 -1
  48. package/dist/ui/assets/{KnowledgeCatalogsCard-CK9bqdf6.js → KnowledgeCatalogsCard-CHopG_j-.js} +1 -1
  49. package/dist/ui/assets/KnowledgeView-CXNKZUJq.js +1 -0
  50. package/dist/ui/assets/{LlamaCppSettings-CdNMHBbp.js → LlamaCppSettings-ohcM7kes.js} +1 -1
  51. package/dist/ui/assets/{MarkdownField-Dugmfr_e.js → MarkdownField-BX0qsaFq.js} +1 -1
  52. package/dist/ui/assets/{MemoriesTree-CgFqUNEr.js → MemoriesTree-BPj5Rod8.js} +1 -1
  53. package/dist/ui/assets/{MicrophoneSettings-DzDe9y1q.js → MicrophoneSettings-CWjeYnfI.js} +1 -1
  54. package/dist/ui/assets/MlxSettings-Dq6dRpcl.js +1 -0
  55. package/dist/ui/assets/{ModelPicker-BVkJhNAH.js → ModelPicker-0Ue-eEKj.js} +1 -1
  56. package/dist/ui/assets/NewPathDialog-BhAZm9dp.js +1 -0
  57. package/dist/ui/assets/{NewScriptDialog-TEAd0KLl.js → NewScriptDialog-DuryIe50.js} +1 -1
  58. package/dist/ui/assets/NewTaskDialog-BX24flMY.js +2 -0
  59. package/dist/ui/assets/{OllamaSettings-CPy2vxyZ.js → OllamaSettings-Boj8Nd1G.js} +1 -1
  60. package/dist/ui/assets/ProjectChat-Dhw_M5bq.js +5 -0
  61. package/dist/ui/assets/ProjectConnectionsTab-BwpMQNrg.js +1 -0
  62. package/dist/ui/assets/{ProjectGitStatusBar-BgHZ2ijN.js → ProjectGitStatusBar-BORGYx5l.js} +1 -1
  63. package/dist/ui/assets/{ProjectGithubView-BV2uTNU0.js → ProjectGithubView-CTP1BOMv.js} +1 -1
  64. package/dist/ui/assets/{ProjectMailTab-DLtJdXSL.js → ProjectMailTab-qFmAeV3M.js} +1 -1
  65. package/dist/ui/assets/{ProjectOverviewView-ZMs9nL5N.js → ProjectOverviewView-Cq1FsoaT.js} +1 -1
  66. package/dist/ui/assets/{ProjectTimeline-CTPcn4Kc.js → ProjectTimeline-Cqae2Z92.js} +1 -1
  67. package/dist/ui/assets/ProjectsView-D0uJjUB-.js +7 -0
  68. package/dist/ui/assets/{RecommendedBadge-iUoisQBi.js → RecommendedBadge-CN1jEmSn.js} +1 -1
  69. package/dist/ui/assets/{RemoteServersPanel-CTVJ0IRh.js → RemoteServersPanel-CMakvCCM.js} +1 -1
  70. package/dist/ui/assets/{ScriptEditorTabs-CCDFZjdC.js → ScriptEditorTabs-st6dJePd.js} +2 -2
  71. package/dist/ui/assets/{ScriptEditorView-CergLqKj.js → ScriptEditorView-BkySh57_.js} +2 -2
  72. package/dist/ui/assets/{ScriptsView-v7ckdhDi.js → ScriptsView-7uPKwjDB.js} +1 -1
  73. package/dist/ui/assets/{SecurityComplianceSettings-Bd0-66Gs.js → SecurityComplianceSettings-Tsv_pXfy.js} +1 -1
  74. package/dist/ui/assets/SessionSwitcher-D0fSeeHO.js +1 -0
  75. package/dist/ui/assets/SettingsView-cli_z8ZW.js +3 -0
  76. package/dist/ui/assets/{SquisqIntegration-C5l_OPvD.js → SquisqIntegration-BTZ1kBlg.js} +1 -1
  77. package/dist/ui/assets/{StorageCleanupDialog-3kv9-2mT.js → StorageCleanupDialog-CDBjl8JQ.js} +1 -1
  78. package/dist/ui/assets/{StorageUsageCard-7sWTrZFa.js → StorageUsageCard-DXY1j0dZ.js} +1 -1
  79. package/dist/ui/assets/TaskTabContent-C0P681SL.js +1 -0
  80. package/dist/ui/assets/TasksView-Ddwz10ri.js +1 -0
  81. package/dist/ui/assets/{TerminalCodeEditor-ChmdzmCz.js → TerminalCodeEditor-BkNQ6QoQ.js} +2 -2
  82. package/dist/ui/assets/ToolsetsEditor-KVigemfL.js +8 -0
  83. package/dist/ui/assets/{TransformToolbarButton-gzIxUBH7.js → TransformToolbarButton-8wfJR1bO.js} +2 -2
  84. package/dist/ui/assets/{UnrecognizedModels-0hptopv6.js → UnrecognizedModels-BzdU1clO.js} +1 -1
  85. package/dist/ui/assets/{VideoEngineSettings-BdNzCEdR.js → VideoEngineSettings-f79ff57u.js} +1 -1
  86. package/dist/ui/assets/{WorkspaceIndexPane-DnsOO916.js → WorkspaceIndexPane-fu5V6o1W.js} +1 -1
  87. package/dist/ui/assets/{api-C0I7spBl.js → api-CmrgM5Rf.js} +1 -1
  88. package/dist/ui/assets/chat-thread-memory-8MCtb17Q.js +1 -0
  89. package/dist/ui/assets/{chunk-6ECMNUIP-BvCy0HUI.js → chunk-6ECMNUIP-D5AA6ozp.js} +1 -1
  90. package/dist/ui/assets/{chunk-A6N6IN3I-ofeM4l8g.js → chunk-A6N6IN3I-BpxihS5H.js} +1 -1
  91. package/dist/ui/assets/{chunk-ATWVNF7D-CYuW1Yc6.js → chunk-ATWVNF7D-CKIWh7bN.js} +1 -1
  92. package/dist/ui/assets/{chunk-UBFT2CDQ-FexGDigd.js → chunk-CW24CH7I-BD0FIooX.js} +1 -1
  93. package/dist/ui/assets/{chunk-DXYWKZ52-zxe8pjH4.js → chunk-DXYWKZ52-DMKPZnpo.js} +1 -1
  94. package/dist/ui/assets/chunk-IIQYS2YH-BtDJt4Xr.js +1 -0
  95. package/dist/ui/assets/{chunk-KGWT454C-v5-l6U5m.js → chunk-KGWT454C-DsQOBuLg.js} +1 -1
  96. package/dist/ui/assets/{chunk-Q77KNJIN-BLuPdsQF.js → chunk-Q77KNJIN-BdWizq9s.js} +1 -1
  97. package/dist/ui/assets/{chunk-USU6HTKB-B_p-YcDp.js → chunk-USU6HTKB-DyGZplh4.js} +1 -1
  98. package/dist/ui/assets/{chunk-UXEANVBI-Bt0kX-0Z.js → chunk-UXEANVBI-BUBXvqyE.js} +1 -1
  99. package/dist/ui/assets/{chunk-O7JILDEF-CqcO1qaI.js → chunk-X7BNDUNI-D14WIvlD.js} +2 -2
  100. package/dist/ui/assets/{chunk-AE3IUKMM-mZjzzO8Z.js → chunk-ZSU5DJLX-CrjQf-vs.js} +1 -1
  101. package/dist/ui/assets/{container-BI8hxN1N.js → container-iFj1r6Hk.js} +1 -1
  102. package/dist/ui/assets/csv-Di411Mv-.js +1 -0
  103. package/dist/ui/assets/data-Q05qqAp4.js +1 -0
  104. package/dist/ui/assets/{dist-APSIK7H3.js → dist-1FNFiksd.js} +3 -3
  105. package/dist/ui/assets/dist-BMZhqfv7.js +2 -0
  106. package/dist/ui/assets/dist-CE5CbmDb.js +225 -0
  107. package/dist/ui/assets/doc-BHcGsJZd.js +587 -0
  108. package/dist/ui/assets/{document-import-DPK4r8Am.js → document-import-B2Ya6sbf.js} +1 -1
  109. package/dist/ui/assets/{docx-DRLuCTaC.js → docx-B8Pwz5Ih.js} +1 -1
  110. package/dist/ui/assets/{epub-a0p2Xb1b.js → epub-BQ4g8Q9j.js} +1 -1
  111. package/dist/ui/assets/{export-options-BqYFyzWx.js → export-options-Dylv69b3.js} +1 -1
  112. package/dist/ui/assets/file-browser-BLOPfnS0.js +5 -0
  113. package/dist/ui/assets/{html-BbQNmJ5X.js → html-BnA7qFwq.js} +1 -1
  114. package/dist/ui/assets/icons-CyM7Cg4E.js +1 -0
  115. package/dist/ui/assets/index-DW6qHqhU.css +1 -0
  116. package/dist/ui/assets/index-DivKnJyx.js +36 -0
  117. package/dist/ui/assets/{mail-link-CWfsP5Aq.js → mail-link-NtlcX5OE.js} +1 -1
  118. package/dist/ui/assets/{markdown-ryKA_OmY.js → markdown-CLKH_zzl.js} +1 -1
  119. package/dist/ui/assets/markdown-baseline-0dqv9qbV.js +1 -0
  120. package/dist/ui/assets/materialize-G4WC5UG3-xq2dcwS8.js +1 -0
  121. package/dist/ui/assets/{monaco-base-C0VTMpv-.js → monaco-base-BSvdAweA.js} +1 -1
  122. package/dist/ui/assets/{monaco-setup-CX8q88c5.js → monaco-setup-CT7LZ0o_.js} +1 -1
  123. package/dist/ui/assets/{new-project-meta-ZmDPGYzC.js → new-project-meta-5Y9Blozr.js} +1 -1
  124. package/dist/ui/assets/outside-in-Msmhxf_U.js +3 -0
  125. package/dist/ui/assets/{pdf-BHrygJa5.js → pdf-C4BhW3zg.js} +1 -1
  126. package/dist/ui/assets/{pending-drafts-27ujtQxX.js → pending-drafts-BD227X9H.js} +1 -1
  127. package/dist/ui/assets/{poppetje-CfaAvFkE.js → poppetje-DvCJO36y.js} +3 -3
  128. package/dist/ui/assets/{pptx-nDW64jAN.js → pptx-B6uaM2s7.js} +3 -3
  129. package/dist/ui/assets/{run-export-86KzLZ7R.js → run-export-TscWwR6y.js} +2 -2
  130. package/dist/ui/assets/{standalone-source-7QdiNsDW.js → standalone-source-Cw9SF7Zk.js} +1 -1
  131. package/dist/ui/assets/storage-Cmhlwx70.js +1 -0
  132. package/dist/ui/assets/styles-BjDaWeMA.css +1 -0
  133. package/dist/ui/assets/styles-CqO-rmOt.js +554 -0
  134. package/dist/ui/assets/{terminal-monaco-setup-Bar-sYKd.js → terminal-monaco-setup-me523-j-.js} +1 -1
  135. package/dist/ui/assets/{transform-CmAXy0Ck.js → transform-DxJCwK68.js} +1 -1
  136. package/dist/ui/assets/{use-local-model-manager-D1yiurrC.js → use-local-model-manager-8wvk-I-y.js} +1 -1
  137. package/dist/ui/assets/{useCompactLayout-BDtPQcDh.js → useCompactLayout-cm4E9Vja.js} +0 -0
  138. package/dist/ui/assets/{useCopilotAvailability-BHOfHrfT.js → useCopilotAvailability-D9hglSH_.js} +1 -1
  139. package/dist/ui/assets/{useDiffpacks-B0kYhlWQ.js → useDiffpacks-1BN2XJWg.js} +1 -1
  140. package/dist/ui/assets/{useGitSync-DOt-ODiw.js → useGitSync-7m9YA7h5.js} +1 -1
  141. package/dist/ui/assets/{useShowWorkInProgressFeatures-BtpredG7.js → useShowWorkInProgressFeatures-D6QOaTUT.js} +1 -1
  142. package/dist/ui/assets/{useTotalRamBytes-B8NFM27w.js → useTotalRamBytes-Durk383U.js} +1 -1
  143. package/dist/ui/assets/{xlsx-B_pu1ZvY.js → xlsx-BbHA9bxA.js} +1 -1
  144. package/dist/ui/index.html +15 -15
  145. package/package.json +12 -11
  146. package/dist/ui/assets/CatalogBrowser-7_jHy5Q3.js +0 -1
  147. package/dist/ui/assets/ChatTimelineView-Cg_kLK_U.js +0 -7
  148. package/dist/ui/assets/CraftbookEditor-BKAIsnXv.js +0 -1
  149. package/dist/ui/assets/DiffpackReviewView-B2a3zgE-.js +0 -1
  150. package/dist/ui/assets/DocumentDetail-GCYhwQqV.js +0 -1
  151. package/dist/ui/assets/DocumentsView-Cm3RaQ5N.js +0 -1
  152. package/dist/ui/assets/FileMapView-BKJovLcL.js +0 -1
  153. package/dist/ui/assets/FoldersSettings-CuJd2JdE.js +0 -1
  154. package/dist/ui/assets/GezelDetail-D_KIPDhQ.js +0 -1
  155. package/dist/ui/assets/GezellenView-BOOW1QQU.js +0 -1
  156. package/dist/ui/assets/HandboekView-gRzJcIbJ.js +0 -1
  157. package/dist/ui/assets/KnowledgeView-DJ3cJVHA.js +0 -1
  158. package/dist/ui/assets/MlxSettings-45mBFHbA.js +0 -1
  159. package/dist/ui/assets/NewTaskDialog-CIXVunZn.js +0 -2
  160. package/dist/ui/assets/ProjectChat-BiJRweob.js +0 -5
  161. package/dist/ui/assets/ProjectConnectionsTab-CQgaIzuv.js +0 -1
  162. package/dist/ui/assets/ProjectsView-BUdR76n6.js +0 -7
  163. package/dist/ui/assets/SessionSwitcher-BgZqyiRn.js +0 -1
  164. package/dist/ui/assets/SettingsView-DLhOYiR5.js +0 -3
  165. package/dist/ui/assets/TaskTabContent-CG2KmfwV.js +0 -1
  166. package/dist/ui/assets/TasksView-Dy5Ue4zS.js +0 -1
  167. package/dist/ui/assets/ToolsetsEditor-J9XxQ5Ms.js +0 -8
  168. package/dist/ui/assets/chat-thread-memory-CI2-giEq.js +0 -1
  169. package/dist/ui/assets/chunk-IIQYS2YH-DEkyBlHg.js +0 -1
  170. package/dist/ui/assets/csv-B0D9jJG2.js +0 -1
  171. package/dist/ui/assets/data-BIL84EaT.js +0 -1
  172. package/dist/ui/assets/dist-CJqyWK6E.js +0 -2
  173. package/dist/ui/assets/dist-DOqbRmFj.js +0 -225
  174. package/dist/ui/assets/doc-C2Ph2FWI.js +0 -584
  175. package/dist/ui/assets/document-companion-aDThLOwl.js +0 -1
  176. package/dist/ui/assets/file-browser-DVyWN0LD.js +0 -5
  177. package/dist/ui/assets/icons-DWaUNQbT.js +0 -1
  178. package/dist/ui/assets/index-DDu8nyO6.js +0 -34
  179. package/dist/ui/assets/index-DEDUSiCx.css +0 -1
  180. package/dist/ui/assets/markdown-baseline-9B52XlX2.js +0 -1
  181. package/dist/ui/assets/materialize-G4WC5UG3-BlZQe-88.js +0 -1
  182. package/dist/ui/assets/outside-in-BmIIeMid.js +0 -3
  183. package/dist/ui/assets/storage-B-vhjyV2.js +0 -1
  184. package/dist/ui/assets/styles-BvkZd-EV.js +0 -550
  185. package/dist/ui/assets/styles-IQ4adxWr.css +0 -1
@@ -611,6 +611,33 @@ def processed_walk(lm, target_hidden, draft_tokens, sampler, processors,
611
611
  return accepted, new_tokens
612
612
 
613
613
 
614
+ def commit_verify_round(verify, lm, cache, accepted: int, block_size: int) -> None:
615
+ """Commit one target-verification transaction across mlx-vlm releases.
616
+
617
+ mlx-vlm 0.7.1 replaced the public-ish ``gdn_states`` result field plus
618
+ direct ``rollback_speculative_cache`` call with a transaction-owned
619
+ ``verify.commit(...)`` method. The latter must run on every round, not
620
+ only a rejection: Qwen4's sparse-attention verifier uses it to finalize
621
+ the target cache even when every draft token was accepted. Keep the
622
+ legacy branch for operator-provided runtimes on the 0.6.17 line.
623
+ """
624
+ commit = getattr(verify, "commit", None)
625
+ if callable(commit):
626
+ commit(lm, cache, accepted, block_size)
627
+ return
628
+
629
+ rollback = getattr(lm, "rollback_speculative_cache", None)
630
+ if accepted < block_size - 1 and callable(rollback):
631
+ rollback(cache, getattr(verify, "gdn_states", None), accepted, block_size)
632
+
633
+
634
+ def abort_verify_round(verify) -> None:
635
+ """Abort a 0.7.1 verification transaction after a contained round error."""
636
+ abort = getattr(verify, "abort", None)
637
+ if callable(abort):
638
+ abort()
639
+
640
+
614
641
  def assisted_rounds(model, spec: SpecState, cache, hidden_tokens: List[int],
615
642
  last_output, first_bonus: int, max_tokens: int, *,
616
643
  sampler, processors, history):
@@ -676,28 +703,53 @@ def assisted_rounds(model, spec: SpecState, cache, hidden_tokens: List[int],
676
703
  if bs <= 1:
677
704
  break
678
705
 
679
- draft_tokens = drafter.draft_block(
680
- b, hidden, None, bs, draw, token_dtype, **draft_kwargs
681
- )
682
- mx.async_eval(draft_tokens)
706
+ verify = None
707
+ try:
708
+ draft_tokens = drafter.draft_block(
709
+ b, hidden, None, bs, draw, token_dtype, **draft_kwargs
710
+ )
711
+ mx.async_eval(draft_tokens)
683
712
 
684
- verify_input = mx.concatenate(
685
- [mx.array([[b]], dtype=token_dtype), draft_tokens], axis=1
686
- )
687
- verify = _mtp_verify_target(
688
- lm, verify_input, cache, draw, sample_target_tokens=False
689
- )
690
- accepted, new_tokens = processed_walk(
691
- lm,
692
- verify.hidden,
693
- draft_tokens,
694
- sampler,
695
- processors,
696
- history,
697
- max_tokens - emitted,
698
- base_position=emitted,
699
- )
700
- _record_speculative_round(drafter, accepted, bs - 1)
713
+ verify_input = mx.concatenate(
714
+ [mx.array([[b]], dtype=token_dtype), draft_tokens], axis=1
715
+ )
716
+ verify = _mtp_verify_target(
717
+ lm, verify_input, cache, draw, sample_target_tokens=False
718
+ )
719
+ accepted, new_tokens = processed_walk(
720
+ lm,
721
+ verify.hidden,
722
+ draft_tokens,
723
+ sampler,
724
+ processors,
725
+ history,
726
+ max_tokens - emitted,
727
+ base_position=emitted,
728
+ )
729
+ _record_speculative_round(drafter, accepted, bs - 1)
730
+
731
+ accept_verified = getattr(drafter, "accept_verified_tokens", None)
732
+ if callable(accept_verified):
733
+ accept_verified(
734
+ verify.hidden,
735
+ draft_tokens,
736
+ accepted,
737
+ new_tokens,
738
+ draw,
739
+ token_dtype,
740
+ **draft_kwargs,
741
+ )
742
+
743
+ # Commit before exposing tokens to the stream: a failed commit
744
+ # must not leave the client with output backed by a dirty cache.
745
+ commit_verify_round(verify, lm, cache, accepted, bs)
746
+ except BaseException:
747
+ if verify is not None:
748
+ abort_verify_round(verify)
749
+ abort_draft = getattr(drafter, "abort_draft_round", None)
750
+ if callable(abort_draft):
751
+ abort_draft()
752
+ raise
701
753
 
702
754
  budget_hit = False
703
755
  for tok in new_tokens:
@@ -707,19 +759,9 @@ def assisted_rounds(model, spec: SpecState, cache, hidden_tokens: List[int],
707
759
  budget_hit = True
708
760
  break
709
761
 
710
- accept_verified = getattr(drafter, "accept_verified_tokens", None)
711
- if callable(accept_verified):
712
- accept_verified(
713
- verify.hidden, draft_tokens, accepted, new_tokens, draw, token_dtype, **draft_kwargs
714
- )
715
-
716
762
  hidden = _mtp_draft_hidden(lm, verify.hidden[:, accepted : accepted + 1, :])
717
763
  b = new_tokens[-1] if new_tokens else b
718
764
 
719
- rollback = getattr(lm, "rollback_speculative_cache", None)
720
- if accepted < bs - 1 and callable(rollback):
721
- rollback(cache, verify.gdn_states, accepted, bs)
722
-
723
765
  shared_kv = _slice_shared_kv_after_reject(
724
766
  verify.shared_kv_states, bs - (accepted + 1)
725
767
  )
@@ -237,12 +237,20 @@ def resolve_tool_markers(processor) -> Optional[Tuple[str, str]]:
237
237
  extraction off and keep the existing text-salvage path.
238
238
  """
239
239
  try:
240
- from mlx_vlm.tool_parsers import ( # type: ignore
240
+ # mlx-vlm 0.7.1 moved the parser-neutral registry into `tools`.
241
+ # Keep the old import for explicitly configured 0.6.17 runtimes.
242
+ from mlx_vlm.tools import ( # type: ignore
241
243
  _infer_tool_parser_from_processor,
242
244
  load_tool_module,
243
245
  )
244
246
  except Exception:
245
- return None
247
+ try:
248
+ from mlx_vlm.tool_parsers import ( # type: ignore
249
+ _infer_tool_parser_from_processor,
250
+ load_tool_module,
251
+ )
252
+ except Exception:
253
+ return None
246
254
  try:
247
255
  parser_type = _infer_tool_parser_from_processor(processor)
248
256
  if not parser_type:
@@ -50,6 +50,21 @@ SUPPORTED_FORMATS = frozenset({"hermes", "gemma", "glm"})
50
50
  _LLG_TOKENIZER_CACHE: Dict[int, Any] = {}
51
51
 
52
52
 
53
+ def _resolve_hf_tokenizer(tokenizer: Any) -> Any:
54
+ """Unwrap mlx-lm's TokenizerWrapper for llguidance.
55
+
56
+ The fast text-tower path exposes a ``TokenizerWrapper`` whose own
57
+ ``is_fast`` flag is true, but ``llguidance.hf.from_tokenizer`` only accepts
58
+ the underlying Hugging Face tokenizer. Hugging Face fast tokenizers also
59
+ have an ``_tokenizer`` attribute, but that object is a low-level
60
+ ``tokenizers.Tokenizer`` without ``is_fast``; requiring the inner object to
61
+ advertise ``is_fast`` therefore unwraps mlx-lm without over-unwrapping an
62
+ ordinary Transformers tokenizer.
63
+ """
64
+ inner = getattr(tokenizer, "_tokenizer", None)
65
+ return inner if getattr(inner, "is_fast", False) else tokenizer
66
+
67
+
53
68
  def _get_llg_tokenizer(tokenizer: Any) -> Any:
54
69
  """Build (and cache) an llguidance tokenizer for a HF tokenizer.
55
70
 
@@ -58,6 +73,7 @@ def _get_llg_tokenizer(tokenizer: Any) -> Any:
58
73
  trick mlx_vlm.structured uses. Keyed by id() since the tokenizer is a
59
74
  singleton held by the loaded model.
60
75
  """
76
+ tokenizer = _resolve_hf_tokenizer(tokenizer)
61
77
  cached = _LLG_TOKENIZER_CACHE.get(id(tokenizer))
62
78
  if cached is not None:
63
79
  return cached
@@ -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-C0I7spBl.js";import{d as i,l as a,p as o,s}from"./primitives-CWrGZpPI.js";import{n as c,t as l}from"./relative-time-B2kBaekd.js";import{O as u,k as d,s as f}from"./chunk-GAZKTT4R-w1SNypWQ.js";import"./schemas-BvLZUsGm.js";var p=e(t(),1),m=n();function h({summary:e,compact:t=!1}){let n=d(e.id),r=u(n.typography.titleFont,f.sans);return(0,m.jsxs)(`span`,{className:`ambient-theme-preview${t?` ambient-theme-preview--compact`:``}`,"data-theme-id":e.id,children:[(0,m.jsx)(`span`,{className:`ambient-theme-name-chip`,style:{background:n.colors.background,borderColor:n.colors.backgroundLight,color:n.colors.text,fontFamily:r},children:e.name}),(0,m.jsxs)(`span`,{className:`ambient-theme-swatches`,"aria-hidden":`true`,children:[(0,m.jsx)(`span`,{className:`ambient-theme-swatch`,style:{background:n.colors.primary}}),(0,m.jsx)(`span`,{className:`ambient-theme-swatch`,style:{background:n.colors.secondary}}),(0,m.jsx)(`span`,{className:`ambient-theme-swatch`,style:{background:n.colors.highlight}})]}),!t&&e.description&&(0,m.jsx)(`span`,{className:`ambient-theme-description`,"aria-hidden":`true`,children:e.description})]})}function g({value:e,themes:t,disabled:n,labelledBy:r,onValueChange:c}){let l=t.find(t=>t.id===e);return(0,m.jsxs)(i,{value:e,onValueChange:e=>c(e),disabled:n,children:[(0,m.jsx)(o,{"aria-labelledby":r,className:`ambient-theme-select-trigger`,style:{width:`100%`,marginTop:`0.25rem`},children:l&&(0,m.jsx)(h,{summary:l,compact:!0})}),(0,m.jsx)(s,{className:`ambient-theme-select-menu`,align:`start`,children:t.map(e=>(0,m.jsx)(a,{value:e.id,textValue:e.name,children:(0,m.jsx)(h,{summary:e})},e.id))})]})}function _(e){return e===`darwin`?{title:`Point macOS at the folder yourself`,lines:[`System Settings → Wallpaper → Add Folder or Album… → choose the ambient folder, then pick a rotation interval.`,`The macOS lock screen follows the desktop wallpaper automatically.`]}:e===`win32`?{title:`Point Windows at the folder yourself`,lines:[`Settings → Personalization → Background → Slideshow → choose the ambient folder.`,`Lock screen: Settings → Personalization → Lock screen → Slideshow → add the ambient folder (turn off Windows Spotlight first).`]}:{title:`Point your desktop at the folder yourself`,lines:[`GNOME and KDE are handled by the automatic toggle above when available.`,`On other desktops, point your environment's wallpaper slideshow at the ambient folder (e.g. XFCE: Desktop settings → Background → Folder).`]}}function v(){let[e,t]=(0,p.useState)(!1),[n,i]=(0,p.useState)(null),[a,o]=(0,p.useState)(null),[s,u]=(0,p.useState)(!1),[d,f]=(0,p.useState)(!1),[h,v]=(0,p.useState)(null),[y,b]=(0,p.useState)(null),x=(0,p.useRef)(null),S=(0,p.useRef)(null),C=window.__GEZEL__?.ambient,w=window.__GEZEL__?.platform,T=(0,p.useCallback)(async()=>{try{let e=await r.getFetch()(r.ambientDashboardLatestUrl(),{headers:r.authHeader()});if(!e.ok)return;let t=await e.blob(),n=URL.createObjectURL(t);S.current&&URL.revokeObjectURL(S.current),S.current=n,v(n)}catch{}},[]),E=(0,p.useCallback)(async()=>{try{let e=await r.getAmbientDashboard();return i(e),t(e.enabled),e}catch{return null}},[]),D=(0,p.useCallback)(async()=>{if(C)try{let e=await C.status();e.ok&&(o(e),u(e.enabled))}catch{}},[C]),O=(0,p.useCallback)(()=>{if(x.current!==null)return;let e=480,t=async()=>{x.current=null;let n=await E();--e,n?.running&&e>0?x.current=window.setTimeout(()=>void t(),2e3):T()};x.current=window.setTimeout(()=>void t(),2e3)},[E,T]);(0,p.useEffect)(()=>(E(),T(),D(),()=>{x.current!==null&&window.clearTimeout(x.current),S.current&&URL.revokeObjectURL(S.current)}),[E,T,D]);let k=(0,p.useCallback)(async n=>{let i=e;t(n),b(null);try{await r.updateConfig({ambientDashboard:{enabled:n}}),E()}catch(e){t(i),b(e instanceof Error?e.message:String(e))}},[e,E]),A=(0,p.useCallback)(async()=>{b(null);try{await r.runAmbientDashboard(),i(e=>e&&{...e,running:!0}),O()}catch(e){b(e instanceof Error?e.message:String(e))}},[O]),j=(0,p.useCallback)(async e=>{if(!n?.themeId||!n.themes?.some(t=>t.id===e))return;let t=e,a=n.themeId;if(t!==a){f(!0),b(null),i(e=>e&&{...e,themeId:t});try{await r.updateConfig({ambientDashboard:{themeId:t}}),await E()}catch(e){i(e=>e&&{...e,themeId:a}),b(e instanceof Error?e.message:String(e))}finally{f(!1)}}},[E,n]),M=(0,p.useCallback)(async e=>{if(!C)return;let t=s;u(e),b(null);let n=e?await C.enable():await C.disable();if(!n.ok){u(t),b(n.error);return}!e&&`reason`in n&&n.reason===`nothing-captured`&&b(`No previous wallpaper was captured, so the current one was left in place.`),D()},[C,s,D]),N=a?.capability,P=C?N&&!N.supported?N.reason===`unknown-desktop`?`Automatic wallpaper is not supported on this desktop (${N.desktop??`unknown`}).`:N.reason===`command-missing`?`The desktop wallpaper tool was not found on this system.`:`Automatic wallpaper is not supported on this platform.`:e?null:`Turn on dashboard generation first.`:`Available in the Gezel desktop app.`,F=_(w),I=n?.themes?.find(e=>e.id===n.themeId),L=!!(n?.lastError&&n.lastFailedAt&&(!n.lastGeneratedAt||Date.parse(n.lastFailedAt)>=Date.parse(n.lastGeneratedAt))),R=y??(L?`Dashboard generation failed: ${n?.lastError}`:null);return(0,m.jsxs)(`section`,{style:{marginBottom:`2rem`},children:[(0,m.jsx)(`h3`,{children:`Ambient display`}),(0,m.jsx)(`p`,{className:`muted`,style:{marginTop:0},children:`When on, your meester composes a dashboard of what moved across your projects — roughly once an hour while the workshop changes — and renders it as an image made to be shown as a wallpaper or lock screen. Images land in the ambient folder; the newest one is always available as latest.png.`}),(0,m.jsxs)(`label`,{className:`debug-toggle`,children:[(0,m.jsx)(`input`,{type:`checkbox`,checked:e,onChange:e=>void k(e.target.checked)}),(0,m.jsx)(`span`,{children:`Generate an ambient dashboard`})]}),e&&(0,m.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.75rem`,alignItems:`flex-start`,flexDirection:`column`,gap:`0.5rem`},children:[n?.themeId&&n.themes&&(0,m.jsxs)(`div`,{style:{width:`min(320px, 100%)`,marginBottom:`0.25rem`},children:[(0,m.jsx)(`span`,{id:`ambient-dashboard-theme-label`,className:`small`,children:`Dashboard theme`}),(0,m.jsx)(g,{value:n.themeId,themes:n.themes,disabled:d||n.running,labelledBy:`ambient-dashboard-theme-label`,onValueChange:e=>void j(e)}),(0,m.jsx)(`p`,{className:`muted small`,style:{margin:`0.25rem 0 0`},children:d?`Saving theme…`:`${I?.description??`Squisq dashboard theme.`} Applies to the next generated image.`})]}),(0,m.jsx)(`span`,{className:`muted small`,title:n?.lastGeneratedAt?l(n.lastGeneratedAt):void 0,children:n?.running?`The meester is composing a dashboard…`:n?.lastGeneratedAt?`Last generated ${c(n.lastGeneratedAt)}`:`Nothing generated yet. The first image may wait for the browser runtime download to finish.`}),(0,m.jsx)(`button`,{type:`button`,onClick:()=>void A(),disabled:n?.running,children:`Generate now`}),h&&(0,m.jsx)(`img`,{src:h,alt:`Latest ambient dashboard`,style:{maxWidth:`min(420px, 100%)`,border:`1px solid var(--border, #8883)`,borderRadius:`4px`}})]}),(0,m.jsxs)(`div`,{style:{marginTop:`1rem`},children:[(0,m.jsxs)(`label`,{className:`debug-toggle`,children:[(0,m.jsx)(`input`,{type:`checkbox`,checked:s,disabled:P!==null,onChange:e=>void M(e.target.checked)}),(0,m.jsx)(`span`,{children:`Keep my desktop wallpaper set to the latest dashboard`})]}),(0,m.jsx)(`p`,{className:`muted small`,style:{marginTop:`0.25rem`},children:P??(N?.canRestore?`Turning this on changes your wallpaper right away; turning it off restores the previous one.`:`Turning this on changes your wallpaper right away. On this desktop the previous wallpaper cannot be restored automatically.`)})]}),C&&(0,m.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.5rem`,gap:`0.5rem`},children:[(0,m.jsx)(`button`,{type:`button`,onClick:()=>void C.openFolder(),children:`Open ambient folder`}),a?.folder&&(0,m.jsx)(`span`,{className:`muted small`,children:a.folder})]}),(0,m.jsxs)(`details`,{style:{marginTop:`0.75rem`},children:[(0,m.jsx)(`summary`,{className:`muted small`,children:F.title}),(0,m.jsx)(`ul`,{className:`muted small`,style:{marginTop:`0.5rem`},children:F.lines.map(e=>(0,m.jsx)(`li`,{children:e},e))})]}),R&&(0,m.jsx)(`p`,{className:`error small`,children:R})]})}export{v as AmbientDashboardCard};
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-CmrgM5Rf.js";import{d as i,l as a,p as o,s}from"./primitives-CWrGZpPI.js";import{n as c,t as l}from"./relative-time-B2kBaekd.js";import{O as u,k as d,s as f}from"./chunk-GAZKTT4R-w1SNypWQ.js";import"./schemas-BvLZUsGm.js";var p=e(t(),1),m=n();function h({summary:e,compact:t=!1}){let n=d(e.id),r=u(n.typography.titleFont,f.sans);return(0,m.jsxs)(`span`,{className:`ambient-theme-preview${t?` ambient-theme-preview--compact`:``}`,"data-theme-id":e.id,children:[(0,m.jsx)(`span`,{className:`ambient-theme-name-chip`,style:{background:n.colors.background,borderColor:n.colors.backgroundLight,color:n.colors.text,fontFamily:r},children:e.name}),(0,m.jsxs)(`span`,{className:`ambient-theme-swatches`,"aria-hidden":`true`,children:[(0,m.jsx)(`span`,{className:`ambient-theme-swatch`,style:{background:n.colors.primary}}),(0,m.jsx)(`span`,{className:`ambient-theme-swatch`,style:{background:n.colors.secondary}}),(0,m.jsx)(`span`,{className:`ambient-theme-swatch`,style:{background:n.colors.highlight}})]}),!t&&e.description&&(0,m.jsx)(`span`,{className:`ambient-theme-description`,"aria-hidden":`true`,children:e.description})]})}function g({value:e,themes:t,disabled:n,labelledBy:r,onValueChange:c}){let l=t.find(t=>t.id===e);return(0,m.jsxs)(i,{value:e,onValueChange:e=>c(e),disabled:n,children:[(0,m.jsx)(o,{"aria-labelledby":r,className:`ambient-theme-select-trigger`,style:{width:`100%`,marginTop:`0.25rem`},children:l&&(0,m.jsx)(h,{summary:l,compact:!0})}),(0,m.jsx)(s,{className:`ambient-theme-select-menu`,align:`start`,children:t.map(e=>(0,m.jsx)(a,{value:e.id,textValue:e.name,children:(0,m.jsx)(h,{summary:e})},e.id))})]})}function _(e){return e===`darwin`?{title:`Point macOS at the folder yourself`,lines:[`System Settings → Wallpaper → Add Folder or Album… → choose the ambient folder, then pick a rotation interval.`,`The macOS lock screen follows the desktop wallpaper automatically.`]}:e===`win32`?{title:`Point Windows at the folder yourself`,lines:[`Settings → Personalization → Background → Slideshow → choose the ambient folder.`,`Lock screen: Settings → Personalization → Lock screen → Slideshow → add the ambient folder (turn off Windows Spotlight first).`]}:{title:`Point your desktop at the folder yourself`,lines:[`GNOME and KDE are handled by the automatic toggle above when available.`,`On other desktops, point your environment's wallpaper slideshow at the ambient folder (e.g. XFCE: Desktop settings → Background → Folder).`]}}function v(){let[e,t]=(0,p.useState)(!1),[n,i]=(0,p.useState)(null),[a,o]=(0,p.useState)(null),[s,u]=(0,p.useState)(!1),[d,f]=(0,p.useState)(!1),[h,v]=(0,p.useState)(null),[y,b]=(0,p.useState)(null),x=(0,p.useRef)(null),S=(0,p.useRef)(null),C=window.__GEZEL__?.ambient,w=window.__GEZEL__?.platform,T=(0,p.useCallback)(async()=>{try{let e=await r.getFetch()(r.ambientDashboardLatestUrl(),{headers:r.authHeader()});if(!e.ok)return;let t=await e.blob(),n=URL.createObjectURL(t);S.current&&URL.revokeObjectURL(S.current),S.current=n,v(n)}catch{}},[]),E=(0,p.useCallback)(async()=>{try{let e=await r.getAmbientDashboard();return i(e),t(e.enabled),e}catch{return null}},[]),D=(0,p.useCallback)(async()=>{if(C)try{let e=await C.status();e.ok&&(o(e),u(e.enabled))}catch{}},[C]),O=(0,p.useCallback)(()=>{if(x.current!==null)return;let e=480,t=async()=>{x.current=null;let n=await E();--e,n?.running&&e>0?x.current=window.setTimeout(()=>void t(),2e3):T()};x.current=window.setTimeout(()=>void t(),2e3)},[E,T]);(0,p.useEffect)(()=>(E(),T(),D(),()=>{x.current!==null&&window.clearTimeout(x.current),S.current&&URL.revokeObjectURL(S.current)}),[E,T,D]);let k=(0,p.useCallback)(async n=>{let i=e;t(n),b(null);try{await r.updateConfig({ambientDashboard:{enabled:n}}),E()}catch(e){t(i),b(e instanceof Error?e.message:String(e))}},[e,E]),A=(0,p.useCallback)(async()=>{b(null);try{await r.runAmbientDashboard(),i(e=>e&&{...e,running:!0}),O()}catch(e){b(e instanceof Error?e.message:String(e))}},[O]),j=(0,p.useCallback)(async e=>{if(!n?.themeId||!n.themes?.some(t=>t.id===e))return;let t=e,a=n.themeId;if(t!==a){f(!0),b(null),i(e=>e&&{...e,themeId:t});try{await r.updateConfig({ambientDashboard:{themeId:t}}),await E()}catch(e){i(e=>e&&{...e,themeId:a}),b(e instanceof Error?e.message:String(e))}finally{f(!1)}}},[E,n]),M=(0,p.useCallback)(async e=>{if(!C)return;let t=s;u(e),b(null);let n=e?await C.enable():await C.disable();if(!n.ok){u(t),b(n.error);return}!e&&`reason`in n&&n.reason===`nothing-captured`&&b(`No previous wallpaper was captured, so the current one was left in place.`),D()},[C,s,D]),N=a?.capability,P=C?N&&!N.supported?N.reason===`unknown-desktop`?`Automatic wallpaper is not supported on this desktop (${N.desktop??`unknown`}).`:N.reason===`command-missing`?`The desktop wallpaper tool was not found on this system.`:`Automatic wallpaper is not supported on this platform.`:e?null:`Turn on dashboard generation first.`:`Available in the Gezel desktop app.`,F=_(w),I=n?.themes?.find(e=>e.id===n.themeId),L=!!(n?.lastError&&n.lastFailedAt&&(!n.lastGeneratedAt||Date.parse(n.lastFailedAt)>=Date.parse(n.lastGeneratedAt))),R=y??(L?`Dashboard generation failed: ${n?.lastError}`:null);return(0,m.jsxs)(`section`,{style:{marginBottom:`2rem`},children:[(0,m.jsx)(`h3`,{children:`Ambient display`}),(0,m.jsx)(`p`,{className:`muted`,style:{marginTop:0},children:`When on, your meester composes a dashboard of what moved across your projects — roughly once an hour while the workshop changes — and renders it as an image made to be shown as a wallpaper or lock screen. Images land in the ambient folder; the newest one is always available as latest.png.`}),(0,m.jsxs)(`label`,{className:`debug-toggle`,children:[(0,m.jsx)(`input`,{type:`checkbox`,checked:e,onChange:e=>void k(e.target.checked)}),(0,m.jsx)(`span`,{children:`Generate an ambient dashboard`})]}),e&&(0,m.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.75rem`,alignItems:`flex-start`,flexDirection:`column`,gap:`0.5rem`},children:[n?.themeId&&n.themes&&(0,m.jsxs)(`div`,{style:{width:`min(320px, 100%)`,marginBottom:`0.25rem`},children:[(0,m.jsx)(`span`,{id:`ambient-dashboard-theme-label`,className:`small`,children:`Dashboard theme`}),(0,m.jsx)(g,{value:n.themeId,themes:n.themes,disabled:d||n.running,labelledBy:`ambient-dashboard-theme-label`,onValueChange:e=>void j(e)}),(0,m.jsx)(`p`,{className:`muted small`,style:{margin:`0.25rem 0 0`},children:d?`Saving theme…`:`${I?.description??`Squisq dashboard theme.`} Applies to the next generated image.`})]}),(0,m.jsx)(`span`,{className:`muted small`,title:n?.lastGeneratedAt?l(n.lastGeneratedAt):void 0,children:n?.running?`The meester is composing a dashboard…`:n?.lastGeneratedAt?`Last generated ${c(n.lastGeneratedAt)}`:`Nothing generated yet. The first image may wait for the browser runtime download to finish.`}),(0,m.jsx)(`button`,{type:`button`,onClick:()=>void A(),disabled:n?.running,children:`Generate now`}),h&&(0,m.jsx)(`img`,{src:h,alt:`Latest ambient dashboard`,style:{maxWidth:`min(420px, 100%)`,border:`1px solid var(--border, #8883)`,borderRadius:`4px`}})]}),(0,m.jsxs)(`div`,{style:{marginTop:`1rem`},children:[(0,m.jsxs)(`label`,{className:`debug-toggle`,children:[(0,m.jsx)(`input`,{type:`checkbox`,checked:s,disabled:P!==null,onChange:e=>void M(e.target.checked)}),(0,m.jsx)(`span`,{children:`Keep my desktop wallpaper set to the latest dashboard`})]}),(0,m.jsx)(`p`,{className:`muted small`,style:{marginTop:`0.25rem`},children:P??(N?.canRestore?`Turning this on changes your wallpaper right away; turning it off restores the previous one.`:`Turning this on changes your wallpaper right away. On this desktop the previous wallpaper cannot be restored automatically.`)})]}),C&&(0,m.jsxs)(`div`,{className:`new-row`,style:{marginTop:`0.5rem`,gap:`0.5rem`},children:[(0,m.jsx)(`button`,{type:`button`,onClick:()=>void C.openFolder(),children:`Open ambient folder`}),a?.folder&&(0,m.jsx)(`span`,{className:`muted small`,children:a.folder})]}),(0,m.jsxs)(`details`,{style:{marginTop:`0.75rem`},children:[(0,m.jsx)(`summary`,{className:`muted small`,children:F.title}),(0,m.jsx)(`ul`,{className:`muted small`,style:{marginTop:`0.5rem`},children:F.lines.map(e=>(0,m.jsx)(`li`,{children:e},e))})]}),R&&(0,m.jsx)(`p`,{className:`error small`,children:R})]})}export{v as AmbientDashboardCard};
@@ -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"./dist-CJqyWK6E.js";import{t as i}from"./api-C0I7spBl.js";import{t as a}from"./ConfirmDialog-Dt1ed4Fh.js";import{t as o}from"./RecommendedBadge-iUoisQBi.js";import{t as s}from"./LicenseButton-D3VmcVG1.js";var c=e(t(),1),l=n();function u(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 d({kind:e,disabledReason:t,onModelsChanged:n,configuredDefaultModelId:r,onSetActiveModel:d}){let[p,m]=(0,c.useState)([]),[h,g]=(0,c.useState)([]),[_,v]=(0,c.useState)(null),[y,b]=(0,c.useState)(new Map),[x,S]=(0,c.useState)(null),C=(0,c.useRef)(y);C.current=y;let w=(0,c.useCallback)(async()=>{try{let[t,n]=await Promise.all([e===`stt`?i.listInstalledSttModels():i.listInstalledTtsModels(),i.listAudioCatalog()]);m(t.models),g(e===`stt`?n.stt:n.tts),v(null)}catch(e){m([]),v(e.message)}},[e]);(0,c.useEffect)(()=>{w()},[w]);let T=(0,c.useCallback)(async t=>{if(C.current.has(t))return;let r=new AbortController;b(e=>new Map(e).set(t,{id:t,bytesWritten:0,totalBytes:0,controller:r}));try{await i.pullAudioModel(e,t,e=>{e.type===`progress`?b(n=>{let r=new Map(n),i=r.get(t);return i?(r.set(t,{...i,bytesWritten:e.bytesWritten,totalBytes:e.totalBytes??i.totalBytes}),r):n}):e.type===`error`&&b(n=>{let r=new Map(n),i=r.get(t);return i&&r.set(t,{...i,error:e.error}),r})},r.signal),setTimeout(()=>{b(e=>{if(e.get(t)?.error)return e;let n=new Map(e);return n.delete(t),n}),w(),n?.()},800)}catch(e){if(r.signal.aborted){b(e=>{let n=new Map(e);return n.delete(t),n});return}b(n=>{let r=new Map(n),i=r.get(t);return i&&r.set(t,{...i,error:e.message}),r})}},[e,w,n]),E=(0,c.useCallback)(e=>{let t=C.current.get(e);if(t?.error){b(t=>{let n=new Map(t);return n.delete(e),n});return}t?.controller.abort()},[]),D=(0,c.useCallback)(async()=>{if(x)try{e===`stt`?await i.deleteSttModel(x):await i.deleteTtsModel(x),await w(),n?.()}catch(e){v(e.message)}finally{S(null)}},[e,x,w,n]),O=new Set(p.map(e=>e.id)),k=!!d&&p.length>1,A=r&&O.has(r)?r:p[0]?.id;return(0,l.jsxs)(`div`,{className:`ollama-model-manager`,children:[y.size>0&&(0,l.jsxs)(`div`,{className:`ollama-section`,children:[(0,l.jsx)(`h4`,{children:`Downloading…`}),(0,l.jsx)(`div`,{className:`ollama-pull-list`,children:Array.from(y.values()).map(e=>(0,l.jsx)(f,{pull:e,onCancel:()=>E(e.id)},e.id))})]}),(p.length>0||_)&&(0,l.jsxs)(`div`,{className:`ollama-section`,children:[(0,l.jsx)(`h4`,{children:`Local models`}),_&&(0,l.jsx)(`p`,{className:`error`,children:_}),k&&(0,l.jsxs)(`p`,{className:`muted small`,children:[`The `,(0,l.jsx)(`strong`,{children:`active`}),` model is the one transcription runs on. The engine binds one model at a time, so switching reloads it — the next transcription takes a moment longer.`]}),p.length>0&&(0,l.jsxs)(`table`,{className:`ollama-model-table`,children:[(0,l.jsx)(`thead`,{children:(0,l.jsxs)(`tr`,{children:[k&&(0,l.jsx)(`th`,{scope:`col`,className:`gz-active-model-column`,children:`Active`}),(0,l.jsx)(`th`,{children:`Name`}),(0,l.jsx)(`th`,{children:`Size`}),(0,l.jsx)(`th`,{children:`Added`}),(0,l.jsx)(`th`,{})]})}),(0,l.jsx)(`tbody`,{children:p.map(t=>(0,l.jsxs)(`tr`,{children:[k&&(0,l.jsx)(`td`,{className:`gz-active-model-column`,children:(0,l.jsx)(`input`,{type:`radio`,name:`active-${e}-model`,className:`gz-active-model-radio`,"aria-label":`Use ${t.id} as the active ${e===`stt`?`speech-to-text`:`text-to-speech`} model`,checked:A===t.id,onChange:()=>{A!==t.id&&d?.(t.id)}})}),(0,l.jsxs)(`td`,{children:[(0,l.jsx)(`code`,{children:t.id}),(0,l.jsx)(`div`,{className:`muted small`,children:t.name})]}),(0,l.jsx)(`td`,{children:u(t.approxSizeBytes)}),(0,l.jsx)(`td`,{className:`muted small`,children:new Date(t.installedAt).toLocaleDateString()}),(0,l.jsx)(`td`,{children:(0,l.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:()=>S(t.id),children:`Delete`})})]},t.id))})]})]}),(0,l.jsxs)(`div`,{className:`ollama-section ollama-section--flat ollama-section--download`,children:[(0,l.jsx)(`h4`,{children:`Download a model`}),h.length===0?(0,l.jsx)(`p`,{className:`muted small`,children:`No models in the catalog yet.`}):(0,l.jsx)(`div`,{className:`catalog-ollama-list`,children:h.map(e=>{let n=O.has(e.id),r=y.get(e.id),i=!!r,a=r&&r.totalBytes>0?Math.min(100,Math.round(r.bytesWritten/r.totalBytes*100)):null;return(0,l.jsxs)(`div`,{className:`catalog-ollama-action`,children:[(0,l.jsxs)(`div`,{className:`catalog-ollama-meta`,children:[(0,l.jsxs)(`div`,{className:`catalog-ollama-specs muted small`,children:[(0,l.jsx)(`code`,{children:e.id}),(0,l.jsx)(`span`,{children:`·`}),(0,l.jsx)(`span`,{children:u(e.approxSizeBytes)})]}),(0,l.jsxs)(`div`,{className:`muted small`,children:[(0,l.jsx)(`strong`,{children:e.name}),` — `,e.description]}),(0,l.jsxs)(`div`,{className:`catalog-ollama-pills`,children:[(0,l.jsx)(s,{manifest:e}),(0,l.jsx)(o,{manifest:e})]})]}),(0,l.jsx)(`button`,{type:`button`,disabled:n||i||!!t,title:t??void 0,onClick:()=>void T(e.id),children:n?`On device`:i?a===null?`Downloading…`:`Downloading… ${a}%`:`Download`})]},e.id)})})]}),(0,l.jsx)(a,{open:x!==null,title:`Delete ${e===`stt`?`STT`:`TTS`} model?`,message:x?`"${x}" will be removed from local storage. This frees disk space; download it again later to use it.`:``,confirmLabel:`Delete`,danger:!0,onCancel:()=>S(null),onConfirm:D})]})}function f({pull:e,onCancel:t}){let n=e.totalBytes>0,r=n?Math.min(100,Math.round(e.bytesWritten/e.totalBytes*100)):0,i=e.error?e.error:n?`Downloading… (${u(e.bytesWritten)} of ${u(e.totalBytes)}, ${r}%)`:e.bytesWritten>0?`Downloading… (${u(e.bytesWritten)})`:`Preparing download…`;return(0,l.jsxs)(`div`,{className:`ollama-pull${e.error?` ollama-pull-error`:``}`,children:[(0,l.jsxs)(`div`,{className:`ollama-pull-head`,children:[(0,l.jsx)(`code`,{children:e.id}),(0,l.jsx)(`span`,{className:`muted small`,children:i}),(0,l.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:t,children:e.error?`Dismiss`:`Cancel`})]}),n?(0,l.jsxs)(`div`,{className:`ollama-pull-bar`,children:[(0,l.jsx)(`div`,{className:`ollama-pull-bar-fill`,style:{width:`${r}%`}}),(0,l.jsxs)(`span`,{className:`ollama-pull-bar-label`,children:[r,`%`]})]}):(0,l.jsx)(`div`,{className:`ollama-pull-bar ollama-pull-bar-indeterminate`,children:(0,l.jsx)(`div`,{className:`ollama-pull-bar-fill`})})]})}function p(){let[e,t]=(0,c.useState)(null),[n,r]=(0,c.useState)(null),[a,o]=(0,c.useState)([]),[s,u]=(0,c.useState)(`af_heart`),[f,p]=(0,c.useState)(`The quick brown fox jumps over the lazy dog.`),[v,y]=(0,c.useState)({kind:`idle`}),[b,x]=(0,c.useState)(void 0),[S,C]=(0,c.useState)(!1),[w,T]=(0,c.useState)(!1),E=(0,c.useRef)(null),D=(0,c.useCallback)(async()=>{try{let[e,n,a]=await Promise.all([i.getAudioEngineStatus(),i.listAudioVoices(),i.getConfig()]);t(e),o(n.voices),C(a.narrateAssistantReplies??!1),x(a.defaultSttModel),r(null)}catch(e){t(null),r(e.message)}},[]);(0,c.useEffect)(()=>{D()},[D]);let O=(0,c.useCallback)(async e=>{T(!0),C(e);try{let t=await i.updateConfig({narrateAssistantReplies:e});window.dispatchEvent(new CustomEvent(`gezel:config-updated`,{detail:t}))}catch(t){C(!e),r(t.message)}finally{T(!1)}},[]),k=(0,c.useCallback)(async e=>{x(e);try{let t=await i.updateConfig({defaultSttModel:e});x(t.defaultSttModel)}catch(e){x(void 0),r(e.message)}},[]),A=(0,c.useCallback)(async()=>{if(f.trim()){y({kind:`synthesizing`});try{let e=await i.synthesizeSpeech({text:f,voice:s,inline:!0});e.b64Wav&&E.current&&(E.current.src=`data:audio/wav;base64,${e.b64Wav}`,await E.current.play().catch(()=>{})),y({kind:`idle`})}catch(e){y({kind:`error`,msg:m(e)})}}},[f,s]);return(0,l.jsxs)(`div`,{className:`provider-card`,children:[(0,l.jsx)(`div`,{className:`settings-card-header`,children:(0,l.jsx)(`h3`,{children:`Audio`})}),(0,l.jsxs)(`p`,{className:`muted small`,children:[`Speech-to-text via the bundled `,(0,l.jsx)(`code`,{children:`whisper.cpp`}),` engine and text-to-speech via the bundled `,(0,l.jsx)(`code`,{children:`Kokoro`}),` engine — both run locally.`]}),n&&(0,l.jsxs)(`p`,{className:`error`,children:[`Couldn't reach the Gezel service. `,n]}),(0,l.jsxs)(`section`,{style:{marginTop:`1rem`},children:[(0,l.jsxs)(`div`,{className:`settings-card-header`,children:[(0,l.jsx)(`h4`,{style:{margin:0},children:`Speech-to-text (whisper.cpp)`}),e&&(0,l.jsx)(g,{engine:e.stt})]}),(0,l.jsx)(_,{engine:e?.stt}),(0,l.jsx)(d,{kind:`stt`,...b?{configuredDefaultModelId:b}:{},onSetActiveModel:k,...h(e?.stt)?{disabledReason:e?.stt.status===`not-configured`?`whisper.cpp engine is not wired up — downloading a model now would still leave it unrunnable.`:`whisper.cpp engine is not reachable.`}:{},onModelsChanged:()=>void D()})]}),(0,l.jsxs)(`section`,{style:{marginTop:`1.5rem`},children:[(0,l.jsxs)(`div`,{className:`settings-card-header`,children:[(0,l.jsx)(`h4`,{style:{margin:0},children:`Text-to-speech (Kokoro)`}),e&&(0,l.jsx)(g,{engine:e.tts})]}),(0,l.jsx)(_,{engine:e?.tts}),(0,l.jsx)(d,{kind:`tts`,...h(e?.tts)?{disabledReason:`Kokoro engine is not configured.`}:{},onModelsChanged:()=>void D()}),e?.tts.status===`ok`&&(0,l.jsx)(`div`,{className:`ollama-section`,style:{marginTop:`1rem`},children:(0,l.jsxs)(`label`,{className:`provider-row`,children:[(0,l.jsx)(`input`,{type:`checkbox`,checked:S,disabled:w,onChange:e=>void O(e.target.checked)}),(0,l.jsxs)(`span`,{children:[`Narrate assistant replies`,(0,l.jsx)(`span`,{className:`muted small`,style:{marginLeft:`0.5rem`},children:`— speak each completed gezel reply aloud using that gezel's voice.`})]})]})}),e?.tts.status===`ok`&&(0,l.jsxs)(`div`,{className:`ollama-section`,style:{marginTop:`1rem`},children:[(0,l.jsx)(`h4`,{children:`Preview a voice`}),(0,l.jsxs)(`div`,{style:{display:`flex`,gap:`0.5rem`,alignItems:`center`,flexWrap:`wrap`},children:[(0,l.jsxs)(`label`,{className:`provider-row`,children:[(0,l.jsx)(`span`,{children:`Voice`}),(0,l.jsx)(`select`,{value:s,onChange:e=>u(e.target.value),children:a.map(e=>(0,l.jsxs)(`option`,{value:e.id,children:[e.name,` (`,e.language,`)`]},e.id))})]}),(0,l.jsx)(`input`,{type:`text`,value:f,onChange:e=>p(e.target.value),style:{minWidth:280,flex:1}}),(0,l.jsx)(`button`,{type:`button`,onClick:()=>void A(),disabled:v.kind===`synthesizing`||!f.trim(),children:v.kind===`synthesizing`?`Synthesizing…`:`Preview`})]}),v.kind===`error`&&(0,l.jsx)(`p`,{className:`error`,children:v.msg}),(0,l.jsx)(`audio`,{ref:E,controls:!0,style:{width:`100%`,marginTop:`0.5rem`}})]})]})]})}function m(e){if(e instanceof r){let t=e.details;if(t&&typeof t==`object`&&`error`in t){let n=t.error;if(typeof n==`string`&&n.length>0)return`${e.message}: ${n}`}if(typeof t==`string`&&t.length>0)return`${e.message}: ${t}`}return e instanceof Error?e.message:String(e)}function h(e){return!e||e.status===`not-configured`||e.status===`unreachable`}function g({engine:e}){return e.status===`ok`?(0,l.jsx)(`span`,{className:`gz-status-pill gz-status-pill--ok`,children:`Ready`}):e.status===`no-model`?(0,l.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,children:`No model`}):e.status===`unreachable`?(0,l.jsx)(`span`,{className:`gz-status-pill gz-status-pill--error`,children:`Unreachable`}):(0,l.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,children:`Not configured`})}function _({engine:e}){return e?e.status===`not-configured`?(0,l.jsxs)(`p`,{className:`muted small`,children:[`Engine isn't wired up on this install yet.`,e.error?(0,l.jsxs)(l.Fragment,{children:[` `,e.error]}):null]}):e.status===`unreachable`?(0,l.jsxs)(`p`,{className:`error`,children:[`Engine isn't responding`,e.baseUrl?(0,l.jsxs)(l.Fragment,{children:[` `,`at `,(0,l.jsx)(`code`,{children:e.baseUrl})]}):null,`.`,e.error?(0,l.jsxs)(l.Fragment,{children:[` `,e.error]}):null]}):e.status===`no-model`?(0,l.jsx)(`p`,{className:`muted small`,children:`Engine is ready — download a model below to start using it.`}):null:null}export{p as AudioEngineSettings};
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-BMZhqfv7.js";import{t as i}from"./api-CmrgM5Rf.js";import{t as a}from"./ConfirmDialog-Dt1ed4Fh.js";import{t as o}from"./RecommendedBadge-CN1jEmSn.js";import{t as s}from"./LicenseButton-D3VmcVG1.js";var c=e(t(),1),l=n();function u(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 d({kind:e,disabledReason:t,onModelsChanged:n,configuredDefaultModelId:r,onSetActiveModel:d}){let[p,m]=(0,c.useState)([]),[h,g]=(0,c.useState)([]),[_,v]=(0,c.useState)(null),[y,b]=(0,c.useState)(new Map),[x,S]=(0,c.useState)(null),C=(0,c.useRef)(y);C.current=y;let w=(0,c.useCallback)(async()=>{try{let[t,n]=await Promise.all([e===`stt`?i.listInstalledSttModels():i.listInstalledTtsModels(),i.listAudioCatalog()]);m(t.models),g(e===`stt`?n.stt:n.tts),v(null)}catch(e){m([]),v(e.message)}},[e]);(0,c.useEffect)(()=>{w()},[w]);let T=(0,c.useCallback)(async t=>{if(C.current.has(t))return;let r=new AbortController;b(e=>new Map(e).set(t,{id:t,bytesWritten:0,totalBytes:0,controller:r}));try{await i.pullAudioModel(e,t,e=>{e.type===`progress`?b(n=>{let r=new Map(n),i=r.get(t);return i?(r.set(t,{...i,bytesWritten:e.bytesWritten,totalBytes:e.totalBytes??i.totalBytes}),r):n}):e.type===`error`&&b(n=>{let r=new Map(n),i=r.get(t);return i&&r.set(t,{...i,error:e.error}),r})},r.signal),setTimeout(()=>{b(e=>{if(e.get(t)?.error)return e;let n=new Map(e);return n.delete(t),n}),w(),n?.()},800)}catch(e){if(r.signal.aborted){b(e=>{let n=new Map(e);return n.delete(t),n});return}b(n=>{let r=new Map(n),i=r.get(t);return i&&r.set(t,{...i,error:e.message}),r})}},[e,w,n]),E=(0,c.useCallback)(e=>{let t=C.current.get(e);if(t?.error){b(t=>{let n=new Map(t);return n.delete(e),n});return}t?.controller.abort()},[]),D=(0,c.useCallback)(async()=>{if(x)try{e===`stt`?await i.deleteSttModel(x):await i.deleteTtsModel(x),await w(),n?.()}catch(e){v(e.message)}finally{S(null)}},[e,x,w,n]),O=new Set(p.map(e=>e.id)),k=!!d&&p.length>1,A=r&&O.has(r)?r:p[0]?.id;return(0,l.jsxs)(`div`,{className:`ollama-model-manager`,children:[y.size>0&&(0,l.jsxs)(`div`,{className:`ollama-section`,children:[(0,l.jsx)(`h4`,{children:`Downloading…`}),(0,l.jsx)(`div`,{className:`ollama-pull-list`,children:Array.from(y.values()).map(e=>(0,l.jsx)(f,{pull:e,onCancel:()=>E(e.id)},e.id))})]}),(p.length>0||_)&&(0,l.jsxs)(`div`,{className:`ollama-section`,children:[(0,l.jsx)(`h4`,{children:`Local models`}),_&&(0,l.jsx)(`p`,{className:`error`,children:_}),k&&(0,l.jsxs)(`p`,{className:`muted small`,children:[`The `,(0,l.jsx)(`strong`,{children:`active`}),` model is the one transcription runs on. The engine binds one model at a time, so switching reloads it — the next transcription takes a moment longer.`]}),p.length>0&&(0,l.jsxs)(`table`,{className:`ollama-model-table`,children:[(0,l.jsx)(`thead`,{children:(0,l.jsxs)(`tr`,{children:[k&&(0,l.jsx)(`th`,{scope:`col`,className:`gz-active-model-column`,children:`Active`}),(0,l.jsx)(`th`,{children:`Name`}),(0,l.jsx)(`th`,{children:`Size`}),(0,l.jsx)(`th`,{children:`Added`}),(0,l.jsx)(`th`,{})]})}),(0,l.jsx)(`tbody`,{children:p.map(t=>(0,l.jsxs)(`tr`,{children:[k&&(0,l.jsx)(`td`,{className:`gz-active-model-column`,children:(0,l.jsx)(`input`,{type:`radio`,name:`active-${e}-model`,className:`gz-active-model-radio`,"aria-label":`Use ${t.id} as the active ${e===`stt`?`speech-to-text`:`text-to-speech`} model`,checked:A===t.id,onChange:()=>{A!==t.id&&d?.(t.id)}})}),(0,l.jsxs)(`td`,{children:[(0,l.jsx)(`code`,{children:t.id}),(0,l.jsx)(`div`,{className:`muted small`,children:t.name})]}),(0,l.jsx)(`td`,{children:u(t.approxSizeBytes)}),(0,l.jsx)(`td`,{className:`muted small`,children:new Date(t.installedAt).toLocaleDateString()}),(0,l.jsx)(`td`,{children:(0,l.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:()=>S(t.id),children:`Delete`})})]},t.id))})]})]}),(0,l.jsxs)(`div`,{className:`ollama-section ollama-section--flat ollama-section--download`,children:[(0,l.jsx)(`h4`,{children:`Download a model`}),h.length===0?(0,l.jsx)(`p`,{className:`muted small`,children:`No models in the catalog yet.`}):(0,l.jsx)(`div`,{className:`catalog-ollama-list`,children:h.map(e=>{let n=O.has(e.id),r=y.get(e.id),i=!!r,a=r&&r.totalBytes>0?Math.min(100,Math.round(r.bytesWritten/r.totalBytes*100)):null;return(0,l.jsxs)(`div`,{className:`catalog-ollama-action`,children:[(0,l.jsxs)(`div`,{className:`catalog-ollama-meta`,children:[(0,l.jsxs)(`div`,{className:`catalog-ollama-specs muted small`,children:[(0,l.jsx)(`code`,{children:e.id}),(0,l.jsx)(`span`,{children:`·`}),(0,l.jsx)(`span`,{children:u(e.approxSizeBytes)})]}),(0,l.jsxs)(`div`,{className:`muted small`,children:[(0,l.jsx)(`strong`,{children:e.name}),` — `,e.description]}),(0,l.jsxs)(`div`,{className:`catalog-ollama-pills`,children:[(0,l.jsx)(s,{manifest:e}),(0,l.jsx)(o,{manifest:e})]})]}),(0,l.jsx)(`button`,{type:`button`,disabled:n||i||!!t,title:t??void 0,onClick:()=>void T(e.id),children:n?`On device`:i?a===null?`Downloading…`:`Downloading… ${a}%`:`Download`})]},e.id)})})]}),(0,l.jsx)(a,{open:x!==null,title:`Delete ${e===`stt`?`STT`:`TTS`} model?`,message:x?`"${x}" will be removed from local storage. This frees disk space; download it again later to use it.`:``,confirmLabel:`Delete`,danger:!0,onCancel:()=>S(null),onConfirm:D})]})}function f({pull:e,onCancel:t}){let n=e.totalBytes>0,r=n?Math.min(100,Math.round(e.bytesWritten/e.totalBytes*100)):0,i=e.error?e.error:n?`Downloading… (${u(e.bytesWritten)} of ${u(e.totalBytes)}, ${r}%)`:e.bytesWritten>0?`Downloading… (${u(e.bytesWritten)})`:`Preparing download…`;return(0,l.jsxs)(`div`,{className:`ollama-pull${e.error?` ollama-pull-error`:``}`,children:[(0,l.jsxs)(`div`,{className:`ollama-pull-head`,children:[(0,l.jsx)(`code`,{children:e.id}),(0,l.jsx)(`span`,{className:`muted small`,children:i}),(0,l.jsx)(`button`,{type:`button`,className:`gz-link-button`,onClick:t,children:e.error?`Dismiss`:`Cancel`})]}),n?(0,l.jsxs)(`div`,{className:`ollama-pull-bar`,children:[(0,l.jsx)(`div`,{className:`ollama-pull-bar-fill`,style:{width:`${r}%`}}),(0,l.jsxs)(`span`,{className:`ollama-pull-bar-label`,children:[r,`%`]})]}):(0,l.jsx)(`div`,{className:`ollama-pull-bar ollama-pull-bar-indeterminate`,children:(0,l.jsx)(`div`,{className:`ollama-pull-bar-fill`})})]})}function p(){let[e,t]=(0,c.useState)(null),[n,r]=(0,c.useState)(null),[a,o]=(0,c.useState)([]),[s,u]=(0,c.useState)(`af_heart`),[f,p]=(0,c.useState)(`The quick brown fox jumps over the lazy dog.`),[v,y]=(0,c.useState)({kind:`idle`}),[b,x]=(0,c.useState)(void 0),[S,C]=(0,c.useState)(!1),[w,T]=(0,c.useState)(!1),E=(0,c.useRef)(null),D=(0,c.useCallback)(async()=>{try{let[e,n,a]=await Promise.all([i.getAudioEngineStatus(),i.listAudioVoices(),i.getConfig()]);t(e),o(n.voices),C(a.narrateAssistantReplies??!1),x(a.defaultSttModel),r(null)}catch(e){t(null),r(e.message)}},[]);(0,c.useEffect)(()=>{D()},[D]);let O=(0,c.useCallback)(async e=>{T(!0),C(e);try{let t=await i.updateConfig({narrateAssistantReplies:e});window.dispatchEvent(new CustomEvent(`gezel:config-updated`,{detail:t}))}catch(t){C(!e),r(t.message)}finally{T(!1)}},[]),k=(0,c.useCallback)(async e=>{x(e);try{let t=await i.updateConfig({defaultSttModel:e});x(t.defaultSttModel)}catch(e){x(void 0),r(e.message)}},[]),A=(0,c.useCallback)(async()=>{if(f.trim()){y({kind:`synthesizing`});try{let e=await i.synthesizeSpeech({text:f,voice:s,inline:!0});e.b64Wav&&E.current&&(E.current.src=`data:audio/wav;base64,${e.b64Wav}`,await E.current.play().catch(()=>{})),y({kind:`idle`})}catch(e){y({kind:`error`,msg:m(e)})}}},[f,s]);return(0,l.jsxs)(`div`,{className:`provider-card`,children:[(0,l.jsx)(`div`,{className:`settings-card-header`,children:(0,l.jsx)(`h3`,{children:`Audio`})}),(0,l.jsxs)(`p`,{className:`muted small`,children:[`Speech-to-text via the bundled `,(0,l.jsx)(`code`,{children:`whisper.cpp`}),` engine and text-to-speech via the bundled `,(0,l.jsx)(`code`,{children:`Kokoro`}),` engine — both run locally.`]}),n&&(0,l.jsxs)(`p`,{className:`error`,children:[`Couldn't reach the Gezel service. `,n]}),(0,l.jsxs)(`section`,{style:{marginTop:`1rem`},children:[(0,l.jsxs)(`div`,{className:`settings-card-header`,children:[(0,l.jsx)(`h4`,{style:{margin:0},children:`Speech-to-text (whisper.cpp)`}),e&&(0,l.jsx)(g,{engine:e.stt})]}),(0,l.jsx)(_,{engine:e?.stt}),(0,l.jsx)(d,{kind:`stt`,...b?{configuredDefaultModelId:b}:{},onSetActiveModel:k,...h(e?.stt)?{disabledReason:e?.stt.status===`not-configured`?`whisper.cpp engine is not wired up — downloading a model now would still leave it unrunnable.`:`whisper.cpp engine is not reachable.`}:{},onModelsChanged:()=>void D()})]}),(0,l.jsxs)(`section`,{style:{marginTop:`1.5rem`},children:[(0,l.jsxs)(`div`,{className:`settings-card-header`,children:[(0,l.jsx)(`h4`,{style:{margin:0},children:`Text-to-speech (Kokoro)`}),e&&(0,l.jsx)(g,{engine:e.tts})]}),(0,l.jsx)(_,{engine:e?.tts}),(0,l.jsx)(d,{kind:`tts`,...h(e?.tts)?{disabledReason:`Kokoro engine is not configured.`}:{},onModelsChanged:()=>void D()}),e?.tts.status===`ok`&&(0,l.jsx)(`div`,{className:`ollama-section`,style:{marginTop:`1rem`},children:(0,l.jsxs)(`label`,{className:`provider-row`,children:[(0,l.jsx)(`input`,{type:`checkbox`,checked:S,disabled:w,onChange:e=>void O(e.target.checked)}),(0,l.jsxs)(`span`,{children:[`Narrate assistant replies`,(0,l.jsx)(`span`,{className:`muted small`,style:{marginLeft:`0.5rem`},children:`— speak each completed gezel reply aloud using that gezel's voice.`})]})]})}),e?.tts.status===`ok`&&(0,l.jsxs)(`div`,{className:`ollama-section`,style:{marginTop:`1rem`},children:[(0,l.jsx)(`h4`,{children:`Preview a voice`}),(0,l.jsxs)(`div`,{style:{display:`flex`,gap:`0.5rem`,alignItems:`center`,flexWrap:`wrap`},children:[(0,l.jsxs)(`label`,{className:`provider-row`,children:[(0,l.jsx)(`span`,{children:`Voice`}),(0,l.jsx)(`select`,{value:s,onChange:e=>u(e.target.value),children:a.map(e=>(0,l.jsxs)(`option`,{value:e.id,children:[e.name,` (`,e.language,`)`]},e.id))})]}),(0,l.jsx)(`input`,{type:`text`,value:f,onChange:e=>p(e.target.value),style:{minWidth:280,flex:1}}),(0,l.jsx)(`button`,{type:`button`,onClick:()=>void A(),disabled:v.kind===`synthesizing`||!f.trim(),children:v.kind===`synthesizing`?`Synthesizing…`:`Preview`})]}),v.kind===`error`&&(0,l.jsx)(`p`,{className:`error`,children:v.msg}),(0,l.jsx)(`audio`,{ref:E,controls:!0,style:{width:`100%`,marginTop:`0.5rem`}})]})]})]})}function m(e){if(e instanceof r){let t=e.details;if(t&&typeof t==`object`&&`error`in t){let n=t.error;if(typeof n==`string`&&n.length>0)return`${e.message}: ${n}`}if(typeof t==`string`&&t.length>0)return`${e.message}: ${t}`}return e instanceof Error?e.message:String(e)}function h(e){return!e||e.status===`not-configured`||e.status===`unreachable`}function g({engine:e}){return e.status===`ok`?(0,l.jsx)(`span`,{className:`gz-status-pill gz-status-pill--ok`,children:`Ready`}):e.status===`no-model`?(0,l.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,children:`No model`}):e.status===`unreachable`?(0,l.jsx)(`span`,{className:`gz-status-pill gz-status-pill--error`,children:`Unreachable`}):(0,l.jsx)(`span`,{className:`gz-status-pill gz-status-pill--warn`,children:`Not configured`})}function _({engine:e}){return e?e.status===`not-configured`?(0,l.jsxs)(`p`,{className:`muted small`,children:[`Engine isn't wired up on this install yet.`,e.error?(0,l.jsxs)(l.Fragment,{children:[` `,e.error]}):null]}):e.status===`unreachable`?(0,l.jsxs)(`p`,{className:`error`,children:[`Engine isn't responding`,e.baseUrl?(0,l.jsxs)(l.Fragment,{children:[` `,`at `,(0,l.jsx)(`code`,{children:e.baseUrl})]}):null,`.`,e.error?(0,l.jsxs)(l.Fragment,{children:[` `,e.error]}):null]}):e.status===`no-model`?(0,l.jsx)(`p`,{className:`muted small`,children:`Engine is ready — download a model below to start using it.`}):null:null}export{p as AudioEngineSettings};
@@ -1,2 +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{t as r}from"./api-C0I7spBl.js";var i=e(t(),1),a=n();function o(e){return e<1e3?`${Math.round(e)}ms`:e<6e4?`${(e/1e3).toFixed(1)}s`:`${Math.floor(e/6e4)}m ${Math.floor(e%6e4/1e3).toString().padStart(2,`0`)}s`}function s(){let[e,t]=(0,i.useState)([]),[n,s]=(0,i.useState)({available:!0,reason:null}),[u,d]=(0,i.useState)(``),[f,p]=(0,i.useState)(``),[m,h]=(0,i.useState)(``),[g,_]=(0,i.useState)(0),[v,y]=(0,i.useState)([]),[b,x]=(0,i.useState)([]),[S,C]=(0,i.useState)(``),[w,T]=(0,i.useState)(`list`),[E,D]=(0,i.useState)(null),[O,k]=(0,i.useState)(null);(0,i.useEffect)(()=>{let e=!1;async function n(){try{let[n,i,a]=await Promise.all([r.listEvalScenarios(),r.getEvalAvailability(),r.listLlamaCppModels().catch(()=>({models:[]}))]);if(e)return;t(n.scenarios.slice()),s(i);let o=a.models.map(e=>typeof e.id==`string`?e.id:null).filter(e=>!!e);if(y(o),n.scenarios.length>0&&!u){let e=n.scenarios[0];e&&(d(e.id),p(e.defaultModel),h(e.defaultImageModel??``))}}catch(t){e||k(t instanceof Error?t.message:String(t))}}return n(),()=>{e=!0}},[u]);let A=(0,i.useCallback)(async()=>{try{let e=await r.listEvalResults({...S?{scenarioId:S}:{},limit:200});x(e.results)}catch(e){k(e instanceof Error?e.message:String(e))}},[S]);(0,i.useEffect)(()=>{A()},[A]);let j=(0,i.useMemo)(()=>e.find(e=>e.id===u),[e,u]),M=(0,i.useCallback)(t=>{d(t);let n=e.find(e=>e.id===t);n&&(p(n.defaultModel),h(n.defaultImageModel??``))},[e]),N=(0,i.useCallback)(async()=>{if(!j)return;let e=new AbortController,t={scenarioId:j.id,modelId:f,startedAt:Date.now(),trialId:null,runDir:null,logTail:[],ac:e};D(t),k(null);try{await r.runEval({scenarioId:j.id,modelId:f,...m?{imageModelId:m}:{},...g>0?{timeoutMs:g*6e4}:{}},e=>{D(t=>{if(!t)return t;let n={...t,logTail:t.logTail};return e.type===`spawned`?(n.trialId=e.trialId??null,n.runDir=e.runDir??null):e.type===`log`?n.logTail=[...t.logTail,e.line].slice(-200):e.type===`error`&&k(e.error),n})},e.signal)}catch(e){k(e instanceof Error?e.message:String(e))}finally{D(null),A()}},[j,f,m,g,A]),P=(0,i.useCallback)(()=>{E&&E.ac.abort()},[E]);return(0,a.jsxs)(`div`,{className:`benchmarks-view`,style:{padding:16},children:[(0,a.jsxs)(`header`,{style:{display:`flex`,alignItems:`baseline`,gap:12},children:[(0,a.jsx)(`h2`,{style:{margin:0},children:`Benchmarks`}),(0,a.jsx)(`span`,{style:{color:`var(--muted)`,fontSize:13},children:`Run eval scenarios and review outcomes on this device.`})]}),!n.available&&(0,a.jsxs)(`div`,{style:{margin:`12px 0`,padding:10,background:`rgba(220, 170, 0, 0.1)`,border:`1px solid rgba(220, 170, 0, 0.35)`,borderRadius:6,fontSize:13},children:[(0,a.jsx)(`strong`,{children:`In-app eval runner unavailable.`}),` `,n.reason??`The harness binary was not found on disk.`,` You can still review past results below; new runs need `,(0,a.jsx)(`code`,{children:`pnpm eval:run`}),` from the repo.`]}),O&&(0,a.jsx)(`div`,{style:{margin:`12px 0`,padding:10,background:`rgba(220, 80, 80, 0.1)`,border:`1px solid rgba(220, 80, 80, 0.35)`,borderRadius:6,fontSize:13},children:O}),(0,a.jsxs)(`section`,{style:{marginTop:16},children:[(0,a.jsx)(`h3`,{style:{marginBottom:8},children:`Run a trial`}),(0,a.jsxs)(`div`,{style:{display:`grid`,gridTemplateColumns:`180px 1fr`,gap:8,alignItems:`center`},children:[(0,a.jsx)(`label`,{htmlFor:`bench-scenario`,children:`Scenario`}),(0,a.jsx)(`select`,{id:`bench-scenario`,value:u,onChange:e=>M(e.currentTarget.value),style:{padding:4},children:e.map(e=>(0,a.jsxs)(`option`,{value:e.id,children:[e.name,` — `,e.capabilityAxis,` `,e.anchored?`(anchored)`:``]},e.id))}),(0,a.jsx)(`label`,{htmlFor:`bench-model`,children:`Model`}),(0,a.jsxs)(`select`,{id:`bench-model`,value:f,onChange:e=>p(e.currentTarget.value),style:{padding:4},children:[(0,a.jsxs)(`option`,{value:j?.defaultModel??``,children:[j?.defaultModel??`(no scenario)`,` (default)`]}),v.filter(e=>e!==j?.defaultModel).map(e=>(0,a.jsxs)(`option`,{value:e,children:[e,` (local)`]},e))]}),j?.defaultImageModel&&(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(`label`,{htmlFor:`bench-image-model`,children:`Image model`}),(0,a.jsx)(`input`,{id:`bench-image-model`,type:`text`,value:m,onChange:e=>h(e.currentTarget.value),style:{padding:4}})]}),(0,a.jsx)(`label`,{htmlFor:`bench-timeout`,children:`Timeout (min)`}),(0,a.jsx)(`input`,{id:`bench-timeout`,type:`number`,min:0,max:120,value:g,onChange:e=>_(Number(e.currentTarget.value)||0),style:{padding:4,width:80}})]}),(0,a.jsxs)(`div`,{style:{marginTop:12,display:`flex`,gap:8},children:[E?(0,a.jsx)(`button`,{type:`button`,onClick:P,children:`Cancel running trial`}):(0,a.jsxs)(`button`,{type:`button`,onClick:()=>void N(),disabled:!j||!f||!n.available,children:[`Run `,j?.name??`scenario`]}),(0,a.jsx)(`span`,{style:{color:`var(--muted)`,fontSize:12,alignSelf:`center`},children:j?`Default timeout: ${Math.round(j.timeoutMs/6e4)} min`:``})]})]}),E&&(0,a.jsxs)(`section`,{style:{marginTop:24},children:[(0,a.jsxs)(`h3`,{style:{marginBottom:8},children:[`Running: `,E.scenarioId,` / `,E.modelId,` `,(0,a.jsxs)(`span`,{style:{color:`var(--muted)`,fontSize:13,fontWeight:`normal`},children:[`(`,o(Date.now()-E.startedAt),`)`]})]}),E.runDir&&(0,a.jsxs)(`div`,{style:{fontSize:12,color:`var(--muted)`},children:[`runDir: `,E.runDir]}),(0,a.jsx)(`pre`,{style:{maxHeight:280,overflow:`auto`,background:`var(--code-bg, #0e1014)`,color:`var(--code-fg, #d6d6d6)`,padding:8,fontSize:12,lineHeight:1.4},children:E.logTail.join(`
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-CmrgM5Rf.js";var i=e(t(),1),a=n();function o(e){return e<1e3?`${Math.round(e)}ms`:e<6e4?`${(e/1e3).toFixed(1)}s`:`${Math.floor(e/6e4)}m ${Math.floor(e%6e4/1e3).toString().padStart(2,`0`)}s`}function s(){let[e,t]=(0,i.useState)([]),[n,s]=(0,i.useState)({available:!0,reason:null}),[u,d]=(0,i.useState)(``),[f,p]=(0,i.useState)(``),[m,h]=(0,i.useState)(``),[g,_]=(0,i.useState)(0),[v,y]=(0,i.useState)([]),[b,x]=(0,i.useState)([]),[S,C]=(0,i.useState)(``),[w,T]=(0,i.useState)(`list`),[E,D]=(0,i.useState)(null),[O,k]=(0,i.useState)(null);(0,i.useEffect)(()=>{let e=!1;async function n(){try{let[n,i,a]=await Promise.all([r.listEvalScenarios(),r.getEvalAvailability(),r.listLlamaCppModels().catch(()=>({models:[]}))]);if(e)return;t(n.scenarios.slice()),s(i);let o=a.models.map(e=>typeof e.id==`string`?e.id:null).filter(e=>!!e);if(y(o),n.scenarios.length>0&&!u){let e=n.scenarios[0];e&&(d(e.id),p(e.defaultModel),h(e.defaultImageModel??``))}}catch(t){e||k(t instanceof Error?t.message:String(t))}}return n(),()=>{e=!0}},[u]);let A=(0,i.useCallback)(async()=>{try{let e=await r.listEvalResults({...S?{scenarioId:S}:{},limit:200});x(e.results)}catch(e){k(e instanceof Error?e.message:String(e))}},[S]);(0,i.useEffect)(()=>{A()},[A]);let j=(0,i.useMemo)(()=>e.find(e=>e.id===u),[e,u]),M=(0,i.useCallback)(t=>{d(t);let n=e.find(e=>e.id===t);n&&(p(n.defaultModel),h(n.defaultImageModel??``))},[e]),N=(0,i.useCallback)(async()=>{if(!j)return;let e=new AbortController,t={scenarioId:j.id,modelId:f,startedAt:Date.now(),trialId:null,runDir:null,logTail:[],ac:e};D(t),k(null);try{await r.runEval({scenarioId:j.id,modelId:f,...m?{imageModelId:m}:{},...g>0?{timeoutMs:g*6e4}:{}},e=>{D(t=>{if(!t)return t;let n={...t,logTail:t.logTail};return e.type===`spawned`?(n.trialId=e.trialId??null,n.runDir=e.runDir??null):e.type===`log`?n.logTail=[...t.logTail,e.line].slice(-200):e.type===`error`&&k(e.error),n})},e.signal)}catch(e){k(e instanceof Error?e.message:String(e))}finally{D(null),A()}},[j,f,m,g,A]),P=(0,i.useCallback)(()=>{E&&E.ac.abort()},[E]);return(0,a.jsxs)(`div`,{className:`benchmarks-view`,style:{padding:16},children:[(0,a.jsxs)(`header`,{style:{display:`flex`,alignItems:`baseline`,gap:12},children:[(0,a.jsx)(`h2`,{style:{margin:0},children:`Benchmarks`}),(0,a.jsx)(`span`,{style:{color:`var(--muted)`,fontSize:13},children:`Run eval scenarios and review outcomes on this device.`})]}),!n.available&&(0,a.jsxs)(`div`,{style:{margin:`12px 0`,padding:10,background:`rgba(220, 170, 0, 0.1)`,border:`1px solid rgba(220, 170, 0, 0.35)`,borderRadius:6,fontSize:13},children:[(0,a.jsx)(`strong`,{children:`In-app eval runner unavailable.`}),` `,n.reason??`The harness binary was not found on disk.`,` You can still review past results below; new runs need `,(0,a.jsx)(`code`,{children:`pnpm eval:run`}),` from the repo.`]}),O&&(0,a.jsx)(`div`,{style:{margin:`12px 0`,padding:10,background:`rgba(220, 80, 80, 0.1)`,border:`1px solid rgba(220, 80, 80, 0.35)`,borderRadius:6,fontSize:13},children:O}),(0,a.jsxs)(`section`,{style:{marginTop:16},children:[(0,a.jsx)(`h3`,{style:{marginBottom:8},children:`Run a trial`}),(0,a.jsxs)(`div`,{style:{display:`grid`,gridTemplateColumns:`180px 1fr`,gap:8,alignItems:`center`},children:[(0,a.jsx)(`label`,{htmlFor:`bench-scenario`,children:`Scenario`}),(0,a.jsx)(`select`,{id:`bench-scenario`,value:u,onChange:e=>M(e.currentTarget.value),style:{padding:4},children:e.map(e=>(0,a.jsxs)(`option`,{value:e.id,children:[e.name,` — `,e.capabilityAxis,` `,e.anchored?`(anchored)`:``]},e.id))}),(0,a.jsx)(`label`,{htmlFor:`bench-model`,children:`Model`}),(0,a.jsxs)(`select`,{id:`bench-model`,value:f,onChange:e=>p(e.currentTarget.value),style:{padding:4},children:[(0,a.jsxs)(`option`,{value:j?.defaultModel??``,children:[j?.defaultModel??`(no scenario)`,` (default)`]}),v.filter(e=>e!==j?.defaultModel).map(e=>(0,a.jsxs)(`option`,{value:e,children:[e,` (local)`]},e))]}),j?.defaultImageModel&&(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(`label`,{htmlFor:`bench-image-model`,children:`Image model`}),(0,a.jsx)(`input`,{id:`bench-image-model`,type:`text`,value:m,onChange:e=>h(e.currentTarget.value),style:{padding:4}})]}),(0,a.jsx)(`label`,{htmlFor:`bench-timeout`,children:`Timeout (min)`}),(0,a.jsx)(`input`,{id:`bench-timeout`,type:`number`,min:0,max:120,value:g,onChange:e=>_(Number(e.currentTarget.value)||0),style:{padding:4,width:80}})]}),(0,a.jsxs)(`div`,{style:{marginTop:12,display:`flex`,gap:8},children:[E?(0,a.jsx)(`button`,{type:`button`,onClick:P,children:`Cancel running trial`}):(0,a.jsxs)(`button`,{type:`button`,onClick:()=>void N(),disabled:!j||!f||!n.available,children:[`Run `,j?.name??`scenario`]}),(0,a.jsx)(`span`,{style:{color:`var(--muted)`,fontSize:12,alignSelf:`center`},children:j?`Default timeout: ${Math.round(j.timeoutMs/6e4)} min`:``})]})]}),E&&(0,a.jsxs)(`section`,{style:{marginTop:24},children:[(0,a.jsxs)(`h3`,{style:{marginBottom:8},children:[`Running: `,E.scenarioId,` / `,E.modelId,` `,(0,a.jsxs)(`span`,{style:{color:`var(--muted)`,fontSize:13,fontWeight:`normal`},children:[`(`,o(Date.now()-E.startedAt),`)`]})]}),E.runDir&&(0,a.jsxs)(`div`,{style:{fontSize:12,color:`var(--muted)`},children:[`runDir: `,E.runDir]}),(0,a.jsx)(`pre`,{style:{maxHeight:280,overflow:`auto`,background:`var(--code-bg, #0e1014)`,color:`var(--code-fg, #d6d6d6)`,padding:8,fontSize:12,lineHeight:1.4},children:E.logTail.join(`
2
2
  `)})]}),(0,a.jsxs)(`section`,{style:{marginTop:24},children:[(0,a.jsxs)(`div`,{style:{display:`flex`,alignItems:`baseline`,gap:12},children:[(0,a.jsxs)(`h3`,{style:{marginBottom:0},children:[`Past results (`,b.length,`)`]}),(0,a.jsxs)(`select`,{value:S,onChange:e=>C(e.currentTarget.value),style:{padding:4},children:[(0,a.jsx)(`option`,{value:``,children:`All scenarios`}),e.map(e=>(0,a.jsx)(`option`,{value:e.id,children:e.name},e.id))]}),(0,a.jsx)(`button`,{type:`button`,onClick:()=>void A(),children:`Refresh`}),(0,a.jsxs)(`span`,{style:{marginLeft:`auto`},children:[(0,a.jsx)(`button`,{type:`button`,onClick:()=>T(`list`),disabled:w===`list`,children:`List`}),(0,a.jsx)(`button`,{type:`button`,onClick:()=>T(`matrix`),disabled:w===`matrix`,children:`Matrix`})]})]}),w===`list`&&(0,a.jsx)(c,{results:b}),w===`matrix`&&(0,a.jsx)(l,{results:b,scenarios:e})]})]})}function c({results:e}){return e.length===0?(0,a.jsx)(`p`,{style:{color:`var(--muted)`,marginTop:12},children:`No results yet for this filter.`}):(0,a.jsxs)(`table`,{style:{marginTop:12,width:`100%`,borderCollapse:`collapse`,fontSize:13},children:[(0,a.jsx)(`thead`,{children:(0,a.jsxs)(`tr`,{style:{borderBottom:`1px solid var(--border, #444)`,textAlign:`left`},children:[(0,a.jsx)(`th`,{style:{padding:`6px 8px`},children:`When`}),(0,a.jsx)(`th`,{style:{padding:`6px 8px`},children:`Scenario`}),(0,a.jsx)(`th`,{style:{padding:`6px 8px`},children:`Model`}),(0,a.jsx)(`th`,{style:{padding:`6px 8px`},children:`Outcome`}),(0,a.jsx)(`th`,{style:{padding:`6px 8px`},children:`Duration`}),(0,a.jsx)(`th`,{style:{padding:`6px 8px`},children:`Reason`})]})}),(0,a.jsx)(`tbody`,{children:e.map(e=>(0,a.jsxs)(`tr`,{style:{borderBottom:`1px solid rgba(128,128,128,0.15)`},children:[(0,a.jsx)(`td`,{style:{padding:`6px 8px`,whiteSpace:`nowrap`},children:new Date(e.startedAt).toLocaleString()}),(0,a.jsx)(`td`,{style:{padding:`6px 8px`},children:e.scenarioId}),(0,a.jsx)(`td`,{style:{padding:`6px 8px`},children:e.modelId}),(0,a.jsx)(`td`,{style:{padding:`6px 8px`},children:e.success?(0,a.jsx)(`span`,{style:{color:`var(--ok, #5bbf5e)`},children:`PASS`}):(0,a.jsxs)(`span`,{style:{color:`var(--fail, #d57070)`},children:[`FAIL`,e.failureMode?` (${e.failureMode})`:``]})}),(0,a.jsx)(`td`,{style:{padding:`6px 8px`},children:o(e.durationMs)}),(0,a.jsx)(`td`,{style:{padding:`6px 8px`,maxWidth:360,overflow:`hidden`,textOverflow:`ellipsis`,whiteSpace:`nowrap`},title:e.reason,children:e.reason})]},e.trialId))})]})}function l({results:e,scenarios:t}){let n=(0,i.useMemo)(()=>{let t=new Map,n=new Set;for(let r of e){let e=`${r.scenarioId}::${r.modelId}`,i=t.get(e);n.add(r.modelId),i?t.set(e,{passes:i.passes+ +!!r.success,total:i.total+1,latest:i.latest}):t.set(e,{passes:+!!r.success,total:1,latest:r})}return{cells:t,models:[...n].sort()}},[e]);return e.length===0?(0,a.jsx)(`p`,{style:{color:`var(--muted)`,marginTop:12},children:`No data to compare yet.`}):(0,a.jsxs)(`table`,{style:{marginTop:12,borderCollapse:`collapse`,fontSize:13},children:[(0,a.jsx)(`thead`,{children:(0,a.jsxs)(`tr`,{style:{borderBottom:`1px solid var(--border, #444)`},children:[(0,a.jsx)(`th`,{style:{padding:`6px 8px`,textAlign:`left`},children:`Scenario`}),n.models.map(e=>(0,a.jsx)(`th`,{style:{padding:`6px 8px`,textAlign:`left`},children:e},e))]})}),(0,a.jsx)(`tbody`,{children:t.map(e=>(0,a.jsxs)(`tr`,{style:{borderBottom:`1px solid rgba(128,128,128,0.15)`},children:[(0,a.jsx)(`td`,{style:{padding:`6px 8px`},children:e.name}),n.models.map(t=>{let r=n.cells.get(`${e.id}::${t}`);if(!r)return(0,a.jsx)(`td`,{style:{padding:`6px 8px`,color:`var(--muted)`},children:`—`},t);let i=Math.round(r.passes/r.total*100);return(0,a.jsxs)(`td`,{style:{padding:`6px 8px`,color:i>=75?`var(--ok, #5bbf5e)`:i>=50?`#cc9b3c`:`var(--fail, #d57070)`},title:`${r.passes}/${r.total} passes — most recent: ${new Date(r.latest.startedAt).toLocaleString()} (${r.latest.success?`PASS`:`FAIL`})`,children:[r.passes,`/`,r.total,` (`,i,`%)`]},t)})]},e.id))})]})}export{s as BenchmarksView};
@@ -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{kt as r,xt as i}from"./dist-CE5CbmDb.js";import{t as a}from"./api-CmrgM5Rf.js";import{n as o}from"./primitives-CWrGZpPI.js";import{at as s}from"./index-DivKnJyx.js";import{t as c}from"./RecommendedBadge-CN1jEmSn.js";var l=e(t(),1),u=n(),d={search:`Search`,"dev-tools":`Dev tools`,data:`Data`,cloud:`Cloud`,productivity:`Productivity`,communication:`Communication`,content:`Content`,ai:`AI`,media:`Media`,other:`Other`},f=[`search`,`dev-tools`,`data`,`cloud`,`productivity`,`communication`,`content`,`media`,`ai`,`other`];function p({item:e}){return(0,u.jsx)(s,{iconSvg:e.iconSvg,logoUrl:e.logoUrl,svgClassName:`catalog-item-logo catalog-item-logo-svg`,imageClassName:`catalog-item-logo`,fallback:(0,u.jsx)(`div`,{className:`catalog-item-logo catalog-item-logo-placeholder`,children:e.manifest.name.slice(0,1)})})}function m(e){return e.manifest.kind===`chat-model`?r(e.manifest):e.manifest.kind===`image-model`||e.manifest.kind===`video-model`?{maker:e.manifest.maintainer.name,customizers:[]}:null}function h(e){let t=e.manifest;return t.kind===`chat-model`||t.kind===`image-model`||t.kind===`video-model`?t:null}function g({kind:e,action:t,emptyMessage:n,filterTags:r,filter:s,onItemsLoaded:g,tagTooltips:_,initialItems:v}){let[y,b]=(0,l.useState)(v??[]),[x,S]=(0,l.useState)(v===void 0),[C,w]=(0,l.useState)(null),[T,E]=(0,l.useState)(``),[D,O]=(0,l.useState)(`all`),k=(0,l.useCallback)(async()=>{S(!0),w(null);try{let t=await a.listCatalogItems(e);b(t.items),g?.(t.items)}catch(e){w(e.message)}finally{S(!1)}},[e,g]);(0,l.useEffect)(()=>{if(v!==void 0){b(v),S(!1);return}k()},[k,v]);let A=(0,l.useMemo)(()=>{if(e!==`toolset`)return null;let t=new Map,n=0;for(let e of y){if(e.manifest.kind!==`toolset`)continue;let r=e.manifest.category??`other`;t.set(r,(t.get(r)??0)+1),n++}return n===0?null:t},[y,e]),j=(0,l.useMemo)(()=>{let t=y;if(e===`toolset`&&D!==`all`&&(t=t.filter(e=>e.manifest.kind===`toolset`&&(e.manifest.category??`other`)===D)),r&&r.length>0){let e=new Set(r);t=t.filter(t=>t.manifest.tags.some(t=>e.has(t.toLowerCase())))}if(T.trim()){let e=T.toLowerCase();t=t.filter(t=>{let n=m(t);return t.manifest.name.toLowerCase().includes(e)||t.manifest.description.toLowerCase().includes(e)||t.manifest.tags.some(t=>t.toLowerCase().includes(e))||t.manifest.id.toLowerCase().includes(e)||n?.maker.toLowerCase().includes(e)||n?.customizers.some(t=>t.toLowerCase().includes(e))})}return s&&(t=t.filter(s)),t},[y,T,r,s,D,e]);return(0,u.jsxs)(`div`,{className:`catalog-browser${e===`chat-model`||e===`image-model`||e===`video-model`||e===`knowledge-catalog`?` catalog-browser--models`:``}`,children:[(0,u.jsxs)(`div`,{className:`catalog-filter`,children:[(0,u.jsx)(`input`,{placeholder:`Filter…`,value:T,onChange:e=>E(e.target.value)}),(0,u.jsx)(`button`,{type:`button`,onClick:()=>void k(),children:`Refresh`})]}),A&&A.size>0&&(0,u.jsxs)(`div`,{className:`catalog-categories`,role:`tablist`,"aria-label":`Filter by category`,children:[(0,u.jsxs)(`button`,{type:`button`,role:`tab`,"aria-selected":D===`all`,className:`catalog-category${D===`all`?` catalog-category-active`:``}`,onClick:()=>O(`all`),children:[`All `,(0,u.jsx)(`span`,{className:`catalog-category-count`,children:y.length})]}),f.filter(e=>(A.get(e)??0)>0).map(e=>(0,u.jsxs)(`button`,{type:`button`,role:`tab`,"aria-selected":D===e,className:`catalog-category${D===e?` catalog-category-active`:``}`,onClick:()=>O(e),children:[d[e],` `,(0,u.jsx)(`span`,{className:`catalog-category-count`,children:A.get(e)})]},e))]}),x&&(0,u.jsx)(`p`,{className:`muted small`,children:`Loading…`}),C&&(0,u.jsx)(`p`,{className:`error`,children:C}),!x&&j.length===0&&(0,u.jsx)(`p`,{className:`muted small`,children:n??`Nothing in the catalog for this kind yet.`}),(0,u.jsx)(`ul`,{className:`catalog-grid`,children:j.map(e=>{let n=m(e),r=h(e),a=i(e.manifest);return(0,u.jsxs)(`li`,{className:`catalog-item`,children:[(0,u.jsxs)(`div`,{className:`catalog-item-header`,children:[(0,u.jsx)(p,{item:e}),(0,u.jsxs)(`div`,{className:`catalog-item-head`,children:[(0,u.jsx)(`div`,{className:`catalog-item-name`,children:e.manifest.name}),e.manifest.kind===`knowledge-catalog`&&(0,u.jsx)(`div`,{className:`catalog-item-attribution`,children:(0,u.jsxs)(`div`,{children:[`Published by `,(0,u.jsx)(`strong`,{children:e.manifest.maintainer.name})]})}),n&&(0,u.jsxs)(`div`,{className:`catalog-item-attribution`,children:[(0,u.jsxs)(`div`,{children:[`Made by `,(0,u.jsx)(`strong`,{children:n.maker})]}),n.customizers.length>0&&(0,u.jsxs)(`div`,{children:[`Customized by `,(0,u.jsx)(`strong`,{children:n.customizers.join(`, `)})]})]}),e.manifest.tags.length>0&&(0,u.jsx)(`div`,{className:`catalog-item-tags`,children:e.manifest.tags.map(e=>{let t=e.trim().toLowerCase(),n=t===`retired`,r=_?.[t]??(n?`This model is kept for compatibility but is no longer recommended for new downloads.`:void 0),i=(0,u.jsx)(`span`,{className:`catalog-item-tag${n?` catalog-item-tag--retired`:``}`,style:r?{cursor:`help`}:void 0,children:e},e);return r?(0,u.jsx)(o,{text:r,children:i},e):i})}),r&&!a&&(0,u.jsx)(c,{manifest:r})]})]}),(0,u.jsx)(`p`,{className:`catalog-item-description`,children:e.manifest.description}),(0,u.jsx)(`div`,{className:`catalog-item-action`,children:t(e)})]},`${e.sourceId}:${e.manifest.id}`)})})]})}export{g 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-C0I7spBl.js";var i=e(t(),1),a=n(),o=0;function s(e=``,t=``){return o+=1,{id:`h-${o}`,key:e,value:t}}function c(e){return e?.channels?.webhook}function l({config:e,onConfigChanged:t}){let n=c(e),[o,l]=(0,i.useState)(n?.url??``),[f,p]=(0,i.useState)(n?.method??`POST`),[m,h]=(0,i.useState)(n?.bodyTemplate??``),[g,_]=(0,i.useState)(n?.bodyContentType??``),[v,y]=(0,i.useState)(()=>Object.entries(n?.headers??{}).map(([e,t])=>s(e,t))),[b,x]=(0,i.useState)(``),[S,C]=(0,i.useState)(``),[w,T]=(0,i.useState)([]),[E,D]=(0,i.useState)({kind:`idle`}),[O,k]=(0,i.useState)(null);(0,i.useEffect)(()=>{let t=c(e);l(t?.url??``),p(t?.method??`POST`),h(t?.bodyTemplate??``),_(t?.bodyContentType??``),y(Object.entries(t?.headers??{}).map(([e,t])=>s(e,t)))},[e]);let A=(0,i.useCallback)(async()=>{try{let e=await r.listChannels();T(e.channels)}catch{}},[]);(0,i.useEffect)(()=>{A()},[A]);let j=w.find(e=>e.name===`webhook`),M=e?.hasWebhookBearerToken??!1,N=e?.hasWebhookBasicAuth??!1,P=(0,i.useCallback)(async()=>{if(!o.trim()){k(`A URL is required.`);return}let n={};for(let e of v){let t=e.key.trim();t&&(n[t]=e.value)}let i={url:o.trim(),method:f,...m.trim()?{bodyTemplate:m}:{},...g.trim()?{bodyContentType:g.trim()}:{},...Object.keys(n).length>0?{headers:n}:{}};k(`saving…`);try{t(await r.updateConfig({channels:{...e?.channels??{},webhook:i},...b.trim()?{webhookBearerToken:b.trim()}:{},...S.trim()?{webhookBasicAuth:S.trim()}:{}})),x(``),C(``),k(`Saved.`),A()}catch(e){k(`Save failed: ${e.message}`)}},[o,f,m,g,v,b,S,e,t,A]),F=(0,i.useCallback)(async()=>{k(`clearing…`);try{t(await r.updateConfig({channels:{...e?.channels??{},webhook:void 0},webhookBearerToken:``,webhookBasicAuth:``})),k(`Cleared.`),A()}catch(e){k(`Clear failed: ${e.message}`)}},[e,t,A]),I=(0,i.useCallback)(async()=>{try{t(await r.updateConfig({webhookBearerToken:``})),k(`Bearer token cleared.`)}catch(e){k(`Clear failed: ${e.message}`)}},[t]),L=(0,i.useCallback)(async()=>{try{t(await r.updateConfig({webhookBasicAuth:``})),k(`Basic auth cleared.`)}catch(e){k(`Clear failed: ${e.message}`)}},[t]),R=(0,i.useCallback)(async()=>{D({kind:`probing`});try{let e=await r.testChannel(`webhook`);e.ok?D({kind:`ok`}):D({kind:`fail`,error:e.error})}catch(e){D({kind:`fail`,error:e.message})}},[]);return(0,a.jsx)(a.Fragment,{children:(0,a.jsxs)(`section`,{className:`provider-card`,children:[(0,a.jsx)(`h3`,{children:`Webhook`}),(0,a.jsx)(`p`,{className:`muted`,style:{marginTop:0},children:`A generic HTTP channel. Gezels (and the service itself) can POST a message here, and whatever listens on the other end decides what to do with it — push to your phone via ntfy.sh, drop into a Slack channel via an incoming webhook, forward to Discord, or relay through a self-hosted service.`}),(0,a.jsx)(u,{status:j}),(0,a.jsxs)(`details`,{className:`home-section-fold`,style:{marginTop:`1rem`},open:!0,children:[(0,a.jsx)(`summary`,{className:`home-section-fold-summary`,children:(0,a.jsx)(`strong`,{children:`Endpoint`})}),(0,a.jsxs)(`div`,{className:`new-row`,style:{flexWrap:`wrap`,marginTop:`0.5rem`},children:[(0,a.jsx)(`input`,{type:`url`,placeholder:`https://ntfy.sh/your-topic`,value:o,onChange:e=>l(e.target.value),style:{flex:`1 1 260px`}}),(0,a.jsxs)(`select`,{value:f,onChange:e=>p(e.target.value),children:[(0,a.jsx)(`option`,{value:`POST`,children:`POST`}),(0,a.jsx)(`option`,{value:`PUT`,children:`PUT`})]})]}),(0,a.jsxs)(`div`,{style:{marginTop:`0.75rem`},children:[(0,a.jsx)(`label`,{className:`muted small`,children:`Headers (optional)`}),(0,a.jsx)(d,{rows:v,onChange:y})]}),(0,a.jsxs)(`div`,{style:{marginTop:`0.75rem`},children:[(0,a.jsxs)(`label`,{className:`muted small`,children:[`Body template (optional — `,(0,a.jsx)(`code`,{children:`{{message}}`}),` is replaced with the JSON-encoded message text)`]}),(0,a.jsx)(`textarea`,{placeholder:`{"message":{{message}}}`,value:m,onChange:e=>h(e.target.value),rows:3,style:{width:`100%`,fontFamily:`var(--font-mono, monospace)`}})]}),(0,a.jsxs)(`div`,{style:{marginTop:`0.5rem`},children:[(0,a.jsx)(`label`,{className:`muted small`,children:`Content-Type (optional, default application/json)`}),(0,a.jsx)(`input`,{type:`text`,placeholder:`application/json`,value:g,onChange:e=>_(e.target.value),style:{width:`100%`}})]})]}),(0,a.jsxs)(`details`,{className:`home-section-fold`,style:{marginTop:`1rem`},children:[(0,a.jsxs)(`summary`,{className:`home-section-fold-summary`,children:[(0,a.jsx)(`strong`,{children:`Auth`}),` `,(0,a.jsx)(`span`,{className:`muted small`,children:M?`— bearer set`:N?`— basic set`:`— none`})]}),(0,a.jsxs)(`div`,{style:{marginTop:`0.5rem`},children:[(0,a.jsx)(`label`,{className:`muted small`,children:`Bearer token (optional)`}),(0,a.jsxs)(`div`,{className:`new-row`,children:[(0,a.jsx)(`input`,{type:`password`,placeholder:M?`Replace bearer token…`:`Paste bearer token`,value:b,onChange:e=>x(e.target.value),style:{flex:1}}),M&&(0,a.jsx)(`button`,{type:`button`,onClick:()=>void I(),children:`Clear`})]})]}),(0,a.jsxs)(`div`,{style:{marginTop:`0.5rem`},children:[(0,a.jsx)(`label`,{className:`muted small`,children:`Basic auth (optional — "user:pass")`}),(0,a.jsxs)(`div`,{className:`new-row`,children:[(0,a.jsx)(`input`,{type:`password`,placeholder:N?`Replace basic auth…`:`user:pass`,value:S,onChange:e=>C(e.target.value),style:{flex:1}}),N&&(0,a.jsx)(`button`,{type:`button`,onClick:()=>void L(),children:`Clear`})]})]})]}),(0,a.jsxs)(`div`,{className:`new-row`,style:{marginTop:`1rem`},children:[(0,a.jsx)(`button`,{type:`button`,className:`primary`,onClick:()=>void P(),children:`Save webhook`}),j?.configured&&(0,a.jsx)(`button`,{type:`button`,onClick:()=>void F(),children:`Remove`}),(0,a.jsx)(`button`,{type:`button`,onClick:()=>void R(),disabled:!j?.configured||E.kind===`probing`,style:{marginLeft:`auto`},children:E.kind===`probing`?`Sending…`:`Send test message`})]}),E.kind===`ok`&&(0,a.jsx)(`p`,{className:`muted small`,style:{marginTop:`0.5rem`},children:`Test sent.`}),E.kind===`fail`&&(0,a.jsxs)(`p`,{className:`error small`,style:{marginTop:`0.5rem`},children:[`Test failed: `,E.error]}),O&&(0,a.jsx)(`p`,{className:`muted small`,style:{marginTop:`0.5rem`},children:O}),(0,a.jsxs)(`details`,{className:`home-section-fold`,style:{marginTop:`1rem`},children:[(0,a.jsx)(`summary`,{className:`home-section-fold-summary`,children:(0,a.jsx)(`strong`,{children:`Recipes`})}),(0,a.jsxs)(`ul`,{className:`muted small`,style:{marginTop:`0.5rem`},children:[(0,a.jsxs)(`li`,{children:[(0,a.jsx)(`strong`,{children:`ntfy.sh (mobile push):`}),` install the ntfy app on your phone, subscribe to a random topic like `,(0,a.jsx)(`code`,{children:`gezel-xyz123`}),`, and paste`,` `,(0,a.jsx)(`code`,{children:`https://ntfy.sh/gezel-xyz123`}),` as the URL. No auth needed; leave the body template blank.`]}),(0,a.jsxs)(`li`,{children:[(0,a.jsx)(`strong`,{children:`Slack:`}),` create an incoming webhook in your workspace, paste the URL. Set the body template to `,(0,a.jsx)(`code`,{children:`{"text":{{message}}}`}),`.`]}),(0,a.jsxs)(`li`,{children:[(0,a.jsx)(`strong`,{children:`Discord:`}),` paste a channel webhook URL. Set the body template to`,` `,(0,a.jsx)(`code`,{children:`{"content":{{message}}}`}),`.`]})]})]})]})})}function u({status:e}){if(!e||!e.configured)return(0,a.jsx)(`p`,{className:`muted small`,style:{marginTop:0},children:`Not configured.`});if(e.ready){let t=e.detail?.url;return(0,a.jsxs)(`p`,{className:`muted small`,style:{marginTop:0},children:[`Active`,t?` — ${t}`:``]})}return(0,a.jsxs)(`p`,{className:`error small`,style:{marginTop:0},children:[`Not ready`,e.lastError?`: ${e.lastError}`:``]})}function d({rows:e,onChange:t}){return(0,a.jsxs)(`div`,{children:[e.map((n,r)=>(0,a.jsxs)(`div`,{className:`new-row`,style:{marginTop:r===0?`0.25rem`:`0.35rem`},children:[(0,a.jsx)(`input`,{type:`text`,placeholder:`Header name`,value:n.key,onChange:i=>{let a=[...e];a[r]={...n,key:i.target.value},t(a)},style:{flex:1}}),(0,a.jsx)(`input`,{type:`text`,placeholder:`Value`,value:n.value,onChange:i=>{let a=[...e];a[r]={...n,value:i.target.value},t(a)},style:{flex:2}}),(0,a.jsx)(`button`,{type:`button`,onClick:()=>t(e.filter((e,t)=>t!==r)),"aria-label":`Remove header`,children:`−`})]},n.id)),(0,a.jsx)(`div`,{style:{marginTop:`0.35rem`},children:(0,a.jsx)(`button`,{type:`button`,onClick:()=>t([...e,s()]),children:`+ Add header`})})]})}export{l as ChannelsSettings};
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-CmrgM5Rf.js";var i=e(t(),1),a=n(),o=0;function s(e=``,t=``){return o+=1,{id:`h-${o}`,key:e,value:t}}function c(e){return e?.channels?.webhook}function l({config:e,onConfigChanged:t}){let n=c(e),[o,l]=(0,i.useState)(n?.url??``),[f,p]=(0,i.useState)(n?.method??`POST`),[m,h]=(0,i.useState)(n?.bodyTemplate??``),[g,_]=(0,i.useState)(n?.bodyContentType??``),[v,y]=(0,i.useState)(()=>Object.entries(n?.headers??{}).map(([e,t])=>s(e,t))),[b,x]=(0,i.useState)(``),[S,C]=(0,i.useState)(``),[w,T]=(0,i.useState)([]),[E,D]=(0,i.useState)({kind:`idle`}),[O,k]=(0,i.useState)(null);(0,i.useEffect)(()=>{let t=c(e);l(t?.url??``),p(t?.method??`POST`),h(t?.bodyTemplate??``),_(t?.bodyContentType??``),y(Object.entries(t?.headers??{}).map(([e,t])=>s(e,t)))},[e]);let A=(0,i.useCallback)(async()=>{try{let e=await r.listChannels();T(e.channels)}catch{}},[]);(0,i.useEffect)(()=>{A()},[A]);let j=w.find(e=>e.name===`webhook`),M=e?.hasWebhookBearerToken??!1,N=e?.hasWebhookBasicAuth??!1,P=(0,i.useCallback)(async()=>{if(!o.trim()){k(`A URL is required.`);return}let n={};for(let e of v){let t=e.key.trim();t&&(n[t]=e.value)}let i={url:o.trim(),method:f,...m.trim()?{bodyTemplate:m}:{},...g.trim()?{bodyContentType:g.trim()}:{},...Object.keys(n).length>0?{headers:n}:{}};k(`saving…`);try{t(await r.updateConfig({channels:{...e?.channels??{},webhook:i},...b.trim()?{webhookBearerToken:b.trim()}:{},...S.trim()?{webhookBasicAuth:S.trim()}:{}})),x(``),C(``),k(`Saved.`),A()}catch(e){k(`Save failed: ${e.message}`)}},[o,f,m,g,v,b,S,e,t,A]),F=(0,i.useCallback)(async()=>{k(`clearing…`);try{t(await r.updateConfig({channels:{...e?.channels??{},webhook:void 0},webhookBearerToken:``,webhookBasicAuth:``})),k(`Cleared.`),A()}catch(e){k(`Clear failed: ${e.message}`)}},[e,t,A]),I=(0,i.useCallback)(async()=>{try{t(await r.updateConfig({webhookBearerToken:``})),k(`Bearer token cleared.`)}catch(e){k(`Clear failed: ${e.message}`)}},[t]),L=(0,i.useCallback)(async()=>{try{t(await r.updateConfig({webhookBasicAuth:``})),k(`Basic auth cleared.`)}catch(e){k(`Clear failed: ${e.message}`)}},[t]),R=(0,i.useCallback)(async()=>{D({kind:`probing`});try{let e=await r.testChannel(`webhook`);e.ok?D({kind:`ok`}):D({kind:`fail`,error:e.error})}catch(e){D({kind:`fail`,error:e.message})}},[]);return(0,a.jsx)(a.Fragment,{children:(0,a.jsxs)(`section`,{className:`provider-card`,children:[(0,a.jsx)(`h3`,{children:`Webhook`}),(0,a.jsx)(`p`,{className:`muted`,style:{marginTop:0},children:`A generic HTTP channel. Gezels (and the service itself) can POST a message here, and whatever listens on the other end decides what to do with it — push to your phone via ntfy.sh, drop into a Slack channel via an incoming webhook, forward to Discord, or relay through a self-hosted service.`}),(0,a.jsx)(u,{status:j}),(0,a.jsxs)(`details`,{className:`home-section-fold`,style:{marginTop:`1rem`},open:!0,children:[(0,a.jsx)(`summary`,{className:`home-section-fold-summary`,children:(0,a.jsx)(`strong`,{children:`Endpoint`})}),(0,a.jsxs)(`div`,{className:`new-row`,style:{flexWrap:`wrap`,marginTop:`0.5rem`},children:[(0,a.jsx)(`input`,{type:`url`,placeholder:`https://ntfy.sh/your-topic`,value:o,onChange:e=>l(e.target.value),style:{flex:`1 1 260px`}}),(0,a.jsxs)(`select`,{value:f,onChange:e=>p(e.target.value),children:[(0,a.jsx)(`option`,{value:`POST`,children:`POST`}),(0,a.jsx)(`option`,{value:`PUT`,children:`PUT`})]})]}),(0,a.jsxs)(`div`,{style:{marginTop:`0.75rem`},children:[(0,a.jsx)(`label`,{className:`muted small`,children:`Headers (optional)`}),(0,a.jsx)(d,{rows:v,onChange:y})]}),(0,a.jsxs)(`div`,{style:{marginTop:`0.75rem`},children:[(0,a.jsxs)(`label`,{className:`muted small`,children:[`Body template (optional — `,(0,a.jsx)(`code`,{children:`{{message}}`}),` is replaced with the JSON-encoded message text)`]}),(0,a.jsx)(`textarea`,{placeholder:`{"message":{{message}}}`,value:m,onChange:e=>h(e.target.value),rows:3,style:{width:`100%`,fontFamily:`var(--font-mono, monospace)`}})]}),(0,a.jsxs)(`div`,{style:{marginTop:`0.5rem`},children:[(0,a.jsx)(`label`,{className:`muted small`,children:`Content-Type (optional, default application/json)`}),(0,a.jsx)(`input`,{type:`text`,placeholder:`application/json`,value:g,onChange:e=>_(e.target.value),style:{width:`100%`}})]})]}),(0,a.jsxs)(`details`,{className:`home-section-fold`,style:{marginTop:`1rem`},children:[(0,a.jsxs)(`summary`,{className:`home-section-fold-summary`,children:[(0,a.jsx)(`strong`,{children:`Auth`}),` `,(0,a.jsx)(`span`,{className:`muted small`,children:M?`— bearer set`:N?`— basic set`:`— none`})]}),(0,a.jsxs)(`div`,{style:{marginTop:`0.5rem`},children:[(0,a.jsx)(`label`,{className:`muted small`,children:`Bearer token (optional)`}),(0,a.jsxs)(`div`,{className:`new-row`,children:[(0,a.jsx)(`input`,{type:`password`,placeholder:M?`Replace bearer token…`:`Paste bearer token`,value:b,onChange:e=>x(e.target.value),style:{flex:1}}),M&&(0,a.jsx)(`button`,{type:`button`,onClick:()=>void I(),children:`Clear`})]})]}),(0,a.jsxs)(`div`,{style:{marginTop:`0.5rem`},children:[(0,a.jsx)(`label`,{className:`muted small`,children:`Basic auth (optional — "user:pass")`}),(0,a.jsxs)(`div`,{className:`new-row`,children:[(0,a.jsx)(`input`,{type:`password`,placeholder:N?`Replace basic auth…`:`user:pass`,value:S,onChange:e=>C(e.target.value),style:{flex:1}}),N&&(0,a.jsx)(`button`,{type:`button`,onClick:()=>void L(),children:`Clear`})]})]})]}),(0,a.jsxs)(`div`,{className:`new-row`,style:{marginTop:`1rem`},children:[(0,a.jsx)(`button`,{type:`button`,className:`primary`,onClick:()=>void P(),children:`Save webhook`}),j?.configured&&(0,a.jsx)(`button`,{type:`button`,onClick:()=>void F(),children:`Remove`}),(0,a.jsx)(`button`,{type:`button`,onClick:()=>void R(),disabled:!j?.configured||E.kind===`probing`,style:{marginLeft:`auto`},children:E.kind===`probing`?`Sending…`:`Send test message`})]}),E.kind===`ok`&&(0,a.jsx)(`p`,{className:`muted small`,style:{marginTop:`0.5rem`},children:`Test sent.`}),E.kind===`fail`&&(0,a.jsxs)(`p`,{className:`error small`,style:{marginTop:`0.5rem`},children:[`Test failed: `,E.error]}),O&&(0,a.jsx)(`p`,{className:`muted small`,style:{marginTop:`0.5rem`},children:O}),(0,a.jsxs)(`details`,{className:`home-section-fold`,style:{marginTop:`1rem`},children:[(0,a.jsx)(`summary`,{className:`home-section-fold-summary`,children:(0,a.jsx)(`strong`,{children:`Recipes`})}),(0,a.jsxs)(`ul`,{className:`muted small`,style:{marginTop:`0.5rem`},children:[(0,a.jsxs)(`li`,{children:[(0,a.jsx)(`strong`,{children:`ntfy.sh (mobile push):`}),` install the ntfy app on your phone, subscribe to a random topic like `,(0,a.jsx)(`code`,{children:`gezel-xyz123`}),`, and paste`,` `,(0,a.jsx)(`code`,{children:`https://ntfy.sh/gezel-xyz123`}),` as the URL. No auth needed; leave the body template blank.`]}),(0,a.jsxs)(`li`,{children:[(0,a.jsx)(`strong`,{children:`Slack:`}),` create an incoming webhook in your workspace, paste the URL. Set the body template to `,(0,a.jsx)(`code`,{children:`{"text":{{message}}}`}),`.`]}),(0,a.jsxs)(`li`,{children:[(0,a.jsx)(`strong`,{children:`Discord:`}),` paste a channel webhook URL. Set the body template to`,` `,(0,a.jsx)(`code`,{children:`{"content":{{message}}}`}),`.`]})]})]})]})})}function u({status:e}){if(!e||!e.configured)return(0,a.jsx)(`p`,{className:`muted small`,style:{marginTop:0},children:`Not configured.`});if(e.ready){let t=e.detail?.url;return(0,a.jsxs)(`p`,{className:`muted small`,style:{marginTop:0},children:[`Active`,t?` — ${t}`:``]})}return(0,a.jsxs)(`p`,{className:`error small`,style:{marginTop:0},children:[`Not ready`,e.lastError?`: ${e.lastError}`:``]})}function d({rows:e,onChange:t}){return(0,a.jsxs)(`div`,{children:[e.map((n,r)=>(0,a.jsxs)(`div`,{className:`new-row`,style:{marginTop:r===0?`0.25rem`:`0.35rem`},children:[(0,a.jsx)(`input`,{type:`text`,placeholder:`Header name`,value:n.key,onChange:i=>{let a=[...e];a[r]={...n,key:i.target.value},t(a)},style:{flex:1}}),(0,a.jsx)(`input`,{type:`text`,placeholder:`Value`,value:n.value,onChange:i=>{let a=[...e];a[r]={...n,value:i.target.value},t(a)},style:{flex:2}}),(0,a.jsx)(`button`,{type:`button`,onClick:()=>t(e.filter((e,t)=>t!==r)),"aria-label":`Remove header`,children:`−`})]},n.id)),(0,a.jsx)(`div`,{style:{marginTop:`0.35rem`},children:(0,a.jsx)(`button`,{type:`button`,onClick:()=>t([...e,s()]),children:`+ Add header`})})]})}export{l as ChannelsSettings};