@agent-native/core 0.76.2 → 0.76.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (429) hide show
  1. package/corpus/core/CHANGELOG.md +14 -0
  2. package/corpus/core/package.json +1 -1
  3. package/corpus/core/src/agent/durable-background.ts +8 -7
  4. package/corpus/core/src/client/AgentPanel.tsx +3 -3
  5. package/corpus/core/src/client/AgentTaskCard.tsx +2 -1
  6. package/corpus/core/src/client/AppearancePicker.tsx +1 -1
  7. package/corpus/core/src/client/AssistantChat.tsx +3 -3
  8. package/corpus/core/src/client/CommandMenu.tsx +4 -4
  9. package/corpus/core/src/client/ErrorBoundary.tsx +1 -1
  10. package/corpus/core/src/client/MultiTabAssistantChat.tsx +11 -11
  11. package/corpus/core/src/client/NewWorkspaceAppFlow.tsx +5 -5
  12. package/corpus/core/src/client/components/ui/dropdown-menu.tsx +9 -9
  13. package/corpus/core/src/client/components/ui/sheet.tsx +1 -1
  14. package/corpus/core/src/client/composer/ComposerPlusMenu.tsx +6 -6
  15. package/corpus/core/src/client/composer/MentionPopover.tsx +4 -4
  16. package/corpus/core/src/client/composer/PastedTextChip.tsx +3 -3
  17. package/corpus/core/src/client/composer/PromptComposer.tsx +3 -3
  18. package/corpus/core/src/client/composer/TiptapComposer.tsx +16 -16
  19. package/corpus/core/src/client/guided-questions.tsx +6 -8
  20. package/corpus/core/src/client/i18n.tsx +2 -2
  21. package/corpus/core/src/client/integrations/IntegrationCard.tsx +2 -2
  22. package/corpus/core/src/client/integrations/IntegrationsPanel.tsx +4 -4
  23. package/corpus/core/src/client/notifications/NotificationsBell.tsx +3 -3
  24. package/corpus/core/src/client/onboarding/OnboardingBanner.tsx +3 -3
  25. package/corpus/core/src/client/onboarding/OnboardingPanel.tsx +17 -10
  26. package/corpus/core/src/client/org/OrgSwitcher.tsx +13 -11
  27. package/corpus/core/src/client/org/TeamPage.tsx +2 -2
  28. package/corpus/core/src/client/settings/AgentsSection.tsx +3 -3
  29. package/corpus/core/src/client/settings/AutomationsSection.tsx +3 -3
  30. package/corpus/core/src/client/settings/SecretsSection.tsx +2 -2
  31. package/corpus/core/src/client/settings/SettingsPanel.tsx +5 -7
  32. package/corpus/core/src/client/settings/SettingsSection.tsx +1 -1
  33. package/corpus/core/src/client/settings/UsageSection.tsx +3 -3
  34. package/corpus/core/src/client/settings/VoiceTranscriptionSection.tsx +3 -3
  35. package/corpus/core/src/client/sharing/ShareButton.tsx +7 -7
  36. package/corpus/core/src/client/sharing/ShareDialog.tsx +3 -3
  37. package/corpus/core/src/deploy/build.ts +2 -2
  38. package/corpus/core/src/styles/agent-conversation.css +10 -10
  39. package/corpus/core/src/styles/blocks.css +2 -2
  40. package/corpus/core/src/styles/rich-markdown-editor.css +2 -2
  41. package/corpus/templates/analytics/app/components/layout/MobileNav.tsx +1 -1
  42. package/corpus/templates/analytics/app/components/ui/alert-dialog.tsx +1 -1
  43. package/corpus/templates/analytics/app/components/ui/alert.tsx +1 -1
  44. package/corpus/templates/analytics/app/components/ui/breadcrumb.tsx +1 -1
  45. package/corpus/templates/analytics/app/components/ui/calendar.tsx +6 -6
  46. package/corpus/templates/analytics/app/components/ui/carousel.tsx +6 -6
  47. package/corpus/templates/analytics/app/components/ui/command.tsx +2 -2
  48. package/corpus/templates/analytics/app/components/ui/context-menu.tsx +9 -9
  49. package/corpus/templates/analytics/app/components/ui/date-picker.tsx +1 -1
  50. package/corpus/templates/analytics/app/components/ui/dialog.tsx +2 -2
  51. package/corpus/templates/analytics/app/components/ui/drawer.tsx +1 -1
  52. package/corpus/templates/analytics/app/components/ui/dropdown-menu.tsx +9 -9
  53. package/corpus/templates/analytics/app/components/ui/input-otp.tsx +1 -1
  54. package/corpus/templates/analytics/app/components/ui/menubar.tsx +9 -9
  55. package/corpus/templates/analytics/app/components/ui/navigation-menu.tsx +3 -3
  56. package/corpus/templates/analytics/app/components/ui/pagination.tsx +4 -4
  57. package/corpus/templates/analytics/app/components/ui/scroll-area.tsx +1 -1
  58. package/corpus/templates/analytics/app/components/ui/select.tsx +3 -3
  59. package/corpus/templates/analytics/app/components/ui/sheet.tsx +2 -2
  60. package/corpus/templates/analytics/app/components/ui/sidebar.tsx +6 -6
  61. package/corpus/templates/analytics/app/components/ui/table.tsx +2 -2
  62. package/corpus/templates/analytics/app/components/ui/toast.tsx +3 -3
  63. package/corpus/templates/assets/app/components/layout/Layout.tsx +2 -2
  64. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +12 -12
  65. package/corpus/templates/assets/app/components/ui/alert-dialog.tsx +1 -1
  66. package/corpus/templates/assets/app/components/ui/alert.tsx +1 -1
  67. package/corpus/templates/assets/app/components/ui/breadcrumb.tsx +1 -1
  68. package/corpus/templates/assets/app/components/ui/dialog.tsx +2 -2
  69. package/corpus/templates/assets/app/components/ui/dropdown-menu.tsx +9 -9
  70. package/corpus/templates/assets/app/components/ui/pagination.tsx +4 -4
  71. package/corpus/templates/assets/app/components/ui/scroll-area.tsx +1 -1
  72. package/corpus/templates/assets/app/components/ui/select.tsx +3 -3
  73. package/corpus/templates/assets/app/components/ui/sheet.tsx +2 -2
  74. package/corpus/templates/assets/app/components/ui/table.tsx +2 -2
  75. package/corpus/templates/assets/app/routes/library.tsx +3 -3
  76. package/corpus/templates/assets/app/routes/settings.tsx +1 -1
  77. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +5 -5
  78. package/corpus/templates/brain/app/components/ui/dropdown-menu.tsx +9 -9
  79. package/corpus/templates/brain/app/components/ui/select.tsx +3 -3
  80. package/corpus/templates/brain/app/components/ui/sheet.tsx +2 -2
  81. package/corpus/templates/brain/app/components/ui/table.tsx +2 -2
  82. package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +6 -6
  83. package/corpus/templates/calendar/app/components/calendar/GoogleSetupWizard.tsx +3 -3
  84. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +11 -9
  85. package/corpus/templates/calendar/app/components/ui/alert-dialog.tsx +1 -1
  86. package/corpus/templates/calendar/app/components/ui/alert.tsx +1 -1
  87. package/corpus/templates/calendar/app/components/ui/breadcrumb.tsx +1 -1
  88. package/corpus/templates/calendar/app/components/ui/calendar.tsx +5 -5
  89. package/corpus/templates/calendar/app/components/ui/carousel.tsx +6 -6
  90. package/corpus/templates/calendar/app/components/ui/command.tsx +2 -2
  91. package/corpus/templates/calendar/app/components/ui/context-menu.tsx +9 -9
  92. package/corpus/templates/calendar/app/components/ui/dialog.tsx +2 -2
  93. package/corpus/templates/calendar/app/components/ui/drawer.tsx +1 -1
  94. package/corpus/templates/calendar/app/components/ui/dropdown-menu.tsx +9 -9
  95. package/corpus/templates/calendar/app/components/ui/input-otp.tsx +1 -1
  96. package/corpus/templates/calendar/app/components/ui/menubar.tsx +9 -9
  97. package/corpus/templates/calendar/app/components/ui/navigation-menu.tsx +3 -3
  98. package/corpus/templates/calendar/app/components/ui/pagination.tsx +4 -4
  99. package/corpus/templates/calendar/app/components/ui/scroll-area.tsx +1 -1
  100. package/corpus/templates/calendar/app/components/ui/select.tsx +3 -3
  101. package/corpus/templates/calendar/app/components/ui/sheet.tsx +2 -2
  102. package/corpus/templates/calendar/app/components/ui/sidebar.tsx +6 -6
  103. package/corpus/templates/calendar/app/components/ui/sonner.tsx +1 -1
  104. package/corpus/templates/calendar/app/components/ui/table.tsx +2 -2
  105. package/corpus/templates/calendar/app/components/ui/toast.tsx +3 -3
  106. package/corpus/templates/calendar/app/pages/Settings.tsx +5 -5
  107. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +9 -9
  108. package/corpus/templates/chat/app/components/ui/alert-dialog.tsx +1 -1
  109. package/corpus/templates/chat/app/components/ui/alert.tsx +1 -1
  110. package/corpus/templates/chat/app/components/ui/breadcrumb.tsx +1 -1
  111. package/corpus/templates/chat/app/components/ui/calendar.tsx +5 -5
  112. package/corpus/templates/chat/app/components/ui/carousel.tsx +6 -6
  113. package/corpus/templates/chat/app/components/ui/command.tsx +2 -2
  114. package/corpus/templates/chat/app/components/ui/context-menu.tsx +9 -9
  115. package/corpus/templates/chat/app/components/ui/dialog.tsx +2 -2
  116. package/corpus/templates/chat/app/components/ui/drawer.tsx +1 -1
  117. package/corpus/templates/chat/app/components/ui/dropdown-menu.tsx +9 -9
  118. package/corpus/templates/chat/app/components/ui/input-otp.tsx +1 -1
  119. package/corpus/templates/chat/app/components/ui/menubar.tsx +9 -9
  120. package/corpus/templates/chat/app/components/ui/navigation-menu.tsx +3 -3
  121. package/corpus/templates/chat/app/components/ui/pagination.tsx +4 -4
  122. package/corpus/templates/chat/app/components/ui/scroll-area.tsx +1 -1
  123. package/corpus/templates/chat/app/components/ui/select.tsx +3 -3
  124. package/corpus/templates/chat/app/components/ui/sheet.tsx +2 -2
  125. package/corpus/templates/chat/app/components/ui/sidebar.tsx +6 -6
  126. package/corpus/templates/chat/app/components/ui/table.tsx +2 -2
  127. package/corpus/templates/chat/app/components/ui/toast.tsx +3 -3
  128. package/corpus/templates/clips/app/components/capture-install-options.tsx +3 -3
  129. package/corpus/templates/clips/app/components/editable-recording-title.tsx +1 -1
  130. package/corpus/templates/clips/app/components/library/bulk-action-toolbar.tsx +3 -3
  131. package/corpus/templates/clips/app/components/library/folder-tree.tsx +5 -5
  132. package/corpus/templates/clips/app/components/library/library-layout.tsx +3 -3
  133. package/corpus/templates/clips/app/components/library/organization-switcher.tsx +4 -4
  134. package/corpus/templates/clips/app/components/library/recording-card.tsx +11 -11
  135. package/corpus/templates/clips/app/components/library/search-bar.tsx +4 -4
  136. package/corpus/templates/clips/app/components/library/space-card.tsx +1 -1
  137. package/corpus/templates/clips/app/components/library/tag-input.tsx +1 -1
  138. package/corpus/templates/clips/app/components/meetings/quick-ask-sidebar.tsx +2 -2
  139. package/corpus/templates/clips/app/components/recorder/camera-visualizer.tsx +2 -2
  140. package/corpus/templates/clips/app/components/recorder/microphone-visualizer.tsx +1 -1
  141. package/corpus/templates/clips/app/components/recorder/pre-record-panel.tsx +4 -4
  142. package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +1 -1
  143. package/corpus/templates/clips/app/components/sharing/share-ui.tsx +2 -2
  144. package/corpus/templates/clips/app/components/ui/alert-dialog.tsx +1 -1
  145. package/corpus/templates/clips/app/components/ui/alert.tsx +1 -1
  146. package/corpus/templates/clips/app/components/ui/breadcrumb.tsx +1 -1
  147. package/corpus/templates/clips/app/components/ui/calendar.tsx +5 -5
  148. package/corpus/templates/clips/app/components/ui/carousel.tsx +6 -6
  149. package/corpus/templates/clips/app/components/ui/command.tsx +2 -2
  150. package/corpus/templates/clips/app/components/ui/context-menu.tsx +9 -9
  151. package/corpus/templates/clips/app/components/ui/dialog.tsx +2 -2
  152. package/corpus/templates/clips/app/components/ui/drawer.tsx +1 -1
  153. package/corpus/templates/clips/app/components/ui/dropdown-menu.tsx +9 -9
  154. package/corpus/templates/clips/app/components/ui/input-otp.tsx +1 -1
  155. package/corpus/templates/clips/app/components/ui/menubar.tsx +9 -9
  156. package/corpus/templates/clips/app/components/ui/navigation-menu.tsx +3 -3
  157. package/corpus/templates/clips/app/components/ui/pagination.tsx +4 -4
  158. package/corpus/templates/clips/app/components/ui/scroll-area.tsx +1 -1
  159. package/corpus/templates/clips/app/components/ui/select.tsx +3 -3
  160. package/corpus/templates/clips/app/components/ui/sheet.tsx +2 -2
  161. package/corpus/templates/clips/app/components/ui/sidebar.tsx +6 -6
  162. package/corpus/templates/clips/app/components/ui/table.tsx +2 -2
  163. package/corpus/templates/clips/app/components/ui/toast.tsx +3 -3
  164. package/corpus/templates/clips/app/components/workspace/branding-editor.tsx +1 -1
  165. package/corpus/templates/clips/app/components/workspace/insights-hub.tsx +2 -2
  166. package/corpus/templates/clips/app/components/workspace/invite-dialog.tsx +2 -2
  167. package/corpus/templates/clips/app/components/workspace/top-creators-table.tsx +6 -6
  168. package/corpus/templates/clips/app/components/workspace/top-videos-table.tsx +2 -2
  169. package/corpus/templates/clips/app/routes/_app.dictate.tsx +4 -4
  170. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +7 -7
  171. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +1 -1
  172. package/corpus/templates/clips/app/routes/download.tsx +2 -2
  173. package/corpus/templates/clips/app/routes/invite.$token.tsx +2 -2
  174. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +3 -3
  175. package/corpus/templates/clips/app/routes/record.tsx +5 -5
  176. package/corpus/templates/clips/app/routes/share.$shareId.tsx +7 -7
  177. package/corpus/templates/content/app/components/EmptyState.tsx +1 -1
  178. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +17 -17
  179. package/corpus/templates/content/app/components/layout/Layout.tsx +2 -2
  180. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +10 -9
  181. package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +10 -6
  182. package/corpus/templates/content/app/components/sidebar/NotionButton.tsx +3 -3
  183. package/corpus/templates/content/app/components/ui/alert-dialog.tsx +1 -1
  184. package/corpus/templates/content/app/components/ui/dialog.tsx +2 -2
  185. package/corpus/templates/content/app/components/ui/dropdown-menu.tsx +9 -9
  186. package/corpus/templates/content/app/components/ui/scroll-area.tsx +1 -1
  187. package/corpus/templates/content/app/components/ui/sheet.tsx +2 -2
  188. package/corpus/templates/content/app/components/ui/table.tsx +2 -2
  189. package/corpus/templates/content/app/components/ui/toast.tsx +3 -3
  190. package/corpus/templates/design/app/components/layout/Layout.tsx +3 -3
  191. package/corpus/templates/design/app/components/layout/Sidebar.tsx +3 -3
  192. package/corpus/templates/design/app/components/ui/alert-dialog.tsx +1 -1
  193. package/corpus/templates/design/app/components/ui/alert.tsx +1 -1
  194. package/corpus/templates/design/app/components/ui/breadcrumb.tsx +1 -1
  195. package/corpus/templates/design/app/components/ui/calendar.tsx +5 -5
  196. package/corpus/templates/design/app/components/ui/carousel.tsx +6 -6
  197. package/corpus/templates/design/app/components/ui/command.tsx +2 -2
  198. package/corpus/templates/design/app/components/ui/context-menu.tsx +9 -9
  199. package/corpus/templates/design/app/components/ui/dialog.tsx +2 -2
  200. package/corpus/templates/design/app/components/ui/drawer.tsx +1 -1
  201. package/corpus/templates/design/app/components/ui/dropdown-menu.tsx +9 -9
  202. package/corpus/templates/design/app/components/ui/input-otp.tsx +1 -1
  203. package/corpus/templates/design/app/components/ui/menubar.tsx +9 -9
  204. package/corpus/templates/design/app/components/ui/navigation-menu.tsx +3 -3
  205. package/corpus/templates/design/app/components/ui/pagination.tsx +4 -4
  206. package/corpus/templates/design/app/components/ui/scroll-area.tsx +1 -1
  207. package/corpus/templates/design/app/components/ui/select.tsx +3 -3
  208. package/corpus/templates/design/app/components/ui/sheet.tsx +2 -2
  209. package/corpus/templates/design/app/components/ui/sidebar.tsx +6 -6
  210. package/corpus/templates/design/app/components/ui/table.tsx +2 -2
  211. package/corpus/templates/design/app/components/ui/toast.tsx +3 -3
  212. package/corpus/templates/design/app/pages/DesignSystems.tsx +6 -8
  213. package/corpus/templates/design/app/pages/Index.tsx +8 -8
  214. package/corpus/templates/design/app/pages/NotFound.tsx +1 -1
  215. package/corpus/templates/design/app/pages/Templates.tsx +2 -2
  216. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +3 -3
  217. package/corpus/templates/forms/app/components/ui/alert-dialog.tsx +1 -1
  218. package/corpus/templates/forms/app/components/ui/alert.tsx +1 -1
  219. package/corpus/templates/forms/app/components/ui/breadcrumb.tsx +1 -1
  220. package/corpus/templates/forms/app/components/ui/calendar.tsx +9 -6
  221. package/corpus/templates/forms/app/components/ui/carousel.tsx +6 -6
  222. package/corpus/templates/forms/app/components/ui/command.tsx +2 -2
  223. package/corpus/templates/forms/app/components/ui/context-menu.tsx +9 -9
  224. package/corpus/templates/forms/app/components/ui/dialog.tsx +2 -2
  225. package/corpus/templates/forms/app/components/ui/drawer.tsx +1 -1
  226. package/corpus/templates/forms/app/components/ui/dropdown-menu.tsx +9 -9
  227. package/corpus/templates/forms/app/components/ui/input-otp.tsx +1 -1
  228. package/corpus/templates/forms/app/components/ui/menubar.tsx +9 -9
  229. package/corpus/templates/forms/app/components/ui/navigation-menu.tsx +3 -3
  230. package/corpus/templates/forms/app/components/ui/pagination.tsx +4 -4
  231. package/corpus/templates/forms/app/components/ui/scroll-area.tsx +1 -1
  232. package/corpus/templates/forms/app/components/ui/select.tsx +3 -3
  233. package/corpus/templates/forms/app/components/ui/sheet.tsx +2 -2
  234. package/corpus/templates/forms/app/components/ui/sidebar.tsx +6 -6
  235. package/corpus/templates/forms/app/components/ui/table.tsx +2 -2
  236. package/corpus/templates/forms/app/components/ui/toast.tsx +3 -3
  237. package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +18 -18
  238. package/corpus/templates/forms/app/pages/FormsListPage.tsx +9 -9
  239. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +4 -4
  240. package/corpus/templates/macros/app/components/ui/alert-dialog.tsx +1 -1
  241. package/corpus/templates/macros/app/components/ui/alert.tsx +1 -1
  242. package/corpus/templates/macros/app/components/ui/breadcrumb.tsx +1 -1
  243. package/corpus/templates/macros/app/components/ui/command.tsx +2 -2
  244. package/corpus/templates/macros/app/components/ui/context-menu.tsx +9 -9
  245. package/corpus/templates/macros/app/components/ui/dialog.tsx +2 -2
  246. package/corpus/templates/macros/app/components/ui/drawer.tsx +1 -1
  247. package/corpus/templates/macros/app/components/ui/dropdown-menu.tsx +9 -9
  248. package/corpus/templates/macros/app/components/ui/menubar.tsx +9 -9
  249. package/corpus/templates/macros/app/components/ui/navigation-menu.tsx +3 -3
  250. package/corpus/templates/macros/app/components/ui/pagination.tsx +4 -4
  251. package/corpus/templates/macros/app/components/ui/scroll-area.tsx +1 -1
  252. package/corpus/templates/macros/app/components/ui/select.tsx +3 -3
  253. package/corpus/templates/macros/app/components/ui/sheet.tsx +2 -2
  254. package/corpus/templates/macros/app/components/ui/table.tsx +2 -2
  255. package/corpus/templates/macros/app/components/ui/toast.tsx +3 -3
  256. package/corpus/templates/macros/app/routes/_index.tsx +2 -2
  257. package/corpus/templates/macros/app/routes/analytics.tsx +1 -1
  258. package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +6 -6
  259. package/corpus/templates/mail/app/components/email/AttachmentStrip.tsx +2 -2
  260. package/corpus/templates/mail/app/components/email/EmailListItem.tsx +5 -5
  261. package/corpus/templates/mail/app/components/email/IntegrationsSidebar.tsx +5 -5
  262. package/corpus/templates/mail/app/components/email/MobileActionBar.tsx +3 -3
  263. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +10 -10
  264. package/corpus/templates/mail/app/components/layout/CommandPalette.tsx +1 -1
  265. package/corpus/templates/mail/app/components/layout/SearchBar.tsx +3 -3
  266. package/corpus/templates/mail/app/components/ui/alert-dialog.tsx +1 -1
  267. package/corpus/templates/mail/app/components/ui/alert.tsx +1 -1
  268. package/corpus/templates/mail/app/components/ui/breadcrumb.tsx +1 -1
  269. package/corpus/templates/mail/app/components/ui/calendar.tsx +4 -4
  270. package/corpus/templates/mail/app/components/ui/carousel.tsx +6 -6
  271. package/corpus/templates/mail/app/components/ui/command.tsx +2 -2
  272. package/corpus/templates/mail/app/components/ui/context-menu.tsx +9 -9
  273. package/corpus/templates/mail/app/components/ui/dialog.tsx +2 -2
  274. package/corpus/templates/mail/app/components/ui/drawer.tsx +1 -1
  275. package/corpus/templates/mail/app/components/ui/dropdown-menu.tsx +9 -9
  276. package/corpus/templates/mail/app/components/ui/input-otp.tsx +1 -1
  277. package/corpus/templates/mail/app/components/ui/menubar.tsx +9 -9
  278. package/corpus/templates/mail/app/components/ui/navigation-menu.tsx +3 -3
  279. package/corpus/templates/mail/app/components/ui/pagination.tsx +4 -4
  280. package/corpus/templates/mail/app/components/ui/scroll-area.tsx +1 -1
  281. package/corpus/templates/mail/app/components/ui/select.tsx +3 -3
  282. package/corpus/templates/mail/app/components/ui/sheet.tsx +2 -2
  283. package/corpus/templates/mail/app/components/ui/sidebar.tsx +6 -6
  284. package/corpus/templates/mail/app/components/ui/sonner.tsx +2 -2
  285. package/corpus/templates/mail/app/components/ui/table.tsx +2 -2
  286. package/corpus/templates/mail/app/components/ui/toast.tsx +3 -3
  287. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +10 -10
  288. package/corpus/templates/plan/app/components/ui/alert-dialog.tsx +1 -1
  289. package/corpus/templates/plan/app/components/ui/alert.tsx +1 -1
  290. package/corpus/templates/plan/app/components/ui/breadcrumb.tsx +1 -1
  291. package/corpus/templates/plan/app/components/ui/calendar.tsx +5 -5
  292. package/corpus/templates/plan/app/components/ui/carousel.tsx +6 -6
  293. package/corpus/templates/plan/app/components/ui/command.tsx +2 -2
  294. package/corpus/templates/plan/app/components/ui/context-menu.tsx +9 -9
  295. package/corpus/templates/plan/app/components/ui/dialog.tsx +2 -2
  296. package/corpus/templates/plan/app/components/ui/drawer.tsx +1 -1
  297. package/corpus/templates/plan/app/components/ui/dropdown-menu.tsx +9 -9
  298. package/corpus/templates/plan/app/components/ui/input-otp.tsx +1 -1
  299. package/corpus/templates/plan/app/components/ui/menubar.tsx +9 -9
  300. package/corpus/templates/plan/app/components/ui/navigation-menu.tsx +3 -3
  301. package/corpus/templates/plan/app/components/ui/pagination.tsx +4 -4
  302. package/corpus/templates/plan/app/components/ui/scroll-area.tsx +1 -1
  303. package/corpus/templates/plan/app/components/ui/select.tsx +3 -3
  304. package/corpus/templates/plan/app/components/ui/sheet.tsx +2 -2
  305. package/corpus/templates/plan/app/components/ui/sidebar.tsx +6 -6
  306. package/corpus/templates/plan/app/components/ui/table.tsx +2 -2
  307. package/corpus/templates/plan/app/components/ui/toast.tsx +3 -3
  308. package/corpus/templates/slides/app/components/layout/Layout.tsx +1 -1
  309. package/corpus/templates/slides/app/components/ui/alert-dialog.tsx +1 -1
  310. package/corpus/templates/slides/app/components/ui/alert.tsx +1 -1
  311. package/corpus/templates/slides/app/components/ui/breadcrumb.tsx +1 -1
  312. package/corpus/templates/slides/app/components/ui/calendar.tsx +5 -5
  313. package/corpus/templates/slides/app/components/ui/carousel.tsx +6 -6
  314. package/corpus/templates/slides/app/components/ui/command.tsx +2 -2
  315. package/corpus/templates/slides/app/components/ui/context-menu.tsx +9 -9
  316. package/corpus/templates/slides/app/components/ui/dialog.tsx +2 -2
  317. package/corpus/templates/slides/app/components/ui/drawer.tsx +1 -1
  318. package/corpus/templates/slides/app/components/ui/dropdown-menu.tsx +9 -9
  319. package/corpus/templates/slides/app/components/ui/input-otp.tsx +1 -1
  320. package/corpus/templates/slides/app/components/ui/menubar.tsx +9 -9
  321. package/corpus/templates/slides/app/components/ui/navigation-menu.tsx +3 -3
  322. package/corpus/templates/slides/app/components/ui/pagination.tsx +4 -4
  323. package/corpus/templates/slides/app/components/ui/scroll-area.tsx +1 -1
  324. package/corpus/templates/slides/app/components/ui/select.tsx +3 -3
  325. package/corpus/templates/slides/app/components/ui/sheet.tsx +2 -2
  326. package/corpus/templates/slides/app/components/ui/sidebar.tsx +6 -6
  327. package/corpus/templates/slides/app/components/ui/table.tsx +2 -2
  328. package/corpus/templates/slides/app/components/ui/toast.tsx +3 -3
  329. package/corpus/templates/videos/app/components/ui/alert-dialog.tsx +1 -1
  330. package/corpus/templates/videos/app/components/ui/alert.tsx +1 -1
  331. package/corpus/templates/videos/app/components/ui/breadcrumb.tsx +1 -1
  332. package/corpus/templates/videos/app/components/ui/calendar.tsx +5 -5
  333. package/corpus/templates/videos/app/components/ui/carousel.tsx +6 -6
  334. package/corpus/templates/videos/app/components/ui/command.tsx +2 -2
  335. package/corpus/templates/videos/app/components/ui/context-menu.tsx +9 -9
  336. package/corpus/templates/videos/app/components/ui/dialog.tsx +2 -2
  337. package/corpus/templates/videos/app/components/ui/drawer.tsx +1 -1
  338. package/corpus/templates/videos/app/components/ui/dropdown-menu.tsx +9 -9
  339. package/corpus/templates/videos/app/components/ui/input-otp.tsx +1 -1
  340. package/corpus/templates/videos/app/components/ui/menubar.tsx +9 -9
  341. package/corpus/templates/videos/app/components/ui/navigation-menu.tsx +3 -3
  342. package/corpus/templates/videos/app/components/ui/pagination.tsx +4 -4
  343. package/corpus/templates/videos/app/components/ui/scroll-area.tsx +1 -1
  344. package/corpus/templates/videos/app/components/ui/select.tsx +3 -3
  345. package/corpus/templates/videos/app/components/ui/sheet.tsx +2 -2
  346. package/corpus/templates/videos/app/components/ui/sidebar.tsx +6 -6
  347. package/corpus/templates/videos/app/components/ui/table.tsx +2 -2
  348. package/corpus/templates/videos/app/components/ui/toast.tsx +3 -3
  349. package/dist/agent/durable-background.d.ts +2 -2
  350. package/dist/agent/durable-background.d.ts.map +1 -1
  351. package/dist/agent/durable-background.js +8 -7
  352. package/dist/agent/durable-background.js.map +1 -1
  353. package/dist/client/AgentPanel.js +3 -3
  354. package/dist/client/AgentPanel.js.map +1 -1
  355. package/dist/client/AgentTaskCard.d.ts.map +1 -1
  356. package/dist/client/AgentTaskCard.js +1 -1
  357. package/dist/client/AgentTaskCard.js.map +1 -1
  358. package/dist/client/AppearancePicker.js +1 -1
  359. package/dist/client/AppearancePicker.js.map +1 -1
  360. package/dist/client/AssistantChat.js +3 -3
  361. package/dist/client/AssistantChat.js.map +1 -1
  362. package/dist/client/CommandMenu.js +4 -4
  363. package/dist/client/CommandMenu.js.map +1 -1
  364. package/dist/client/ErrorBoundary.js +1 -1
  365. package/dist/client/ErrorBoundary.js.map +1 -1
  366. package/dist/client/MultiTabAssistantChat.js +9 -9
  367. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  368. package/dist/client/NewWorkspaceAppFlow.js +5 -5
  369. package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
  370. package/dist/client/components/ui/dropdown-menu.js +6 -6
  371. package/dist/client/components/ui/dropdown-menu.js.map +1 -1
  372. package/dist/client/components/ui/sheet.js +1 -1
  373. package/dist/client/components/ui/sheet.js.map +1 -1
  374. package/dist/client/composer/ComposerPlusMenu.js +5 -5
  375. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  376. package/dist/client/composer/MentionPopover.js +4 -4
  377. package/dist/client/composer/MentionPopover.js.map +1 -1
  378. package/dist/client/composer/PastedTextChip.js +2 -2
  379. package/dist/client/composer/PastedTextChip.js.map +1 -1
  380. package/dist/client/composer/PromptComposer.js +3 -3
  381. package/dist/client/composer/PromptComposer.js.map +1 -1
  382. package/dist/client/composer/TiptapComposer.js +12 -12
  383. package/dist/client/composer/TiptapComposer.js.map +1 -1
  384. package/dist/client/guided-questions.d.ts.map +1 -1
  385. package/dist/client/guided-questions.js +5 -5
  386. package/dist/client/guided-questions.js.map +1 -1
  387. package/dist/client/i18n.js +2 -2
  388. package/dist/client/i18n.js.map +1 -1
  389. package/dist/client/integrations/IntegrationCard.js +1 -1
  390. package/dist/client/integrations/IntegrationCard.js.map +1 -1
  391. package/dist/client/integrations/IntegrationsPanel.js +4 -4
  392. package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
  393. package/dist/client/notifications/NotificationsBell.js +3 -3
  394. package/dist/client/notifications/NotificationsBell.js.map +1 -1
  395. package/dist/client/onboarding/OnboardingBanner.js +3 -3
  396. package/dist/client/onboarding/OnboardingBanner.js.map +1 -1
  397. package/dist/client/onboarding/OnboardingPanel.d.ts.map +1 -1
  398. package/dist/client/onboarding/OnboardingPanel.js +15 -10
  399. package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
  400. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  401. package/dist/client/org/OrgSwitcher.js +7 -7
  402. package/dist/client/org/OrgSwitcher.js.map +1 -1
  403. package/dist/client/org/TeamPage.js +2 -2
  404. package/dist/client/org/TeamPage.js.map +1 -1
  405. package/dist/client/settings/AgentsSection.js +3 -3
  406. package/dist/client/settings/AgentsSection.js.map +1 -1
  407. package/dist/client/settings/AutomationsSection.js +2 -2
  408. package/dist/client/settings/AutomationsSection.js.map +1 -1
  409. package/dist/client/settings/SecretsSection.js +2 -2
  410. package/dist/client/settings/SecretsSection.js.map +1 -1
  411. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  412. package/dist/client/settings/SettingsPanel.js +4 -4
  413. package/dist/client/settings/SettingsPanel.js.map +1 -1
  414. package/dist/client/settings/SettingsSection.js +1 -1
  415. package/dist/client/settings/SettingsSection.js.map +1 -1
  416. package/dist/client/settings/UsageSection.js +2 -2
  417. package/dist/client/settings/UsageSection.js.map +1 -1
  418. package/dist/client/settings/VoiceTranscriptionSection.js +3 -3
  419. package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
  420. package/dist/client/sharing/ShareButton.js +6 -6
  421. package/dist/client/sharing/ShareButton.js.map +1 -1
  422. package/dist/client/sharing/ShareDialog.js +3 -3
  423. package/dist/client/sharing/ShareDialog.js.map +1 -1
  424. package/dist/deploy/build.js +2 -2
  425. package/dist/deploy/build.js.map +1 -1
  426. package/dist/styles/agent-conversation.css +10 -10
  427. package/dist/styles/blocks.css +2 -2
  428. package/dist/styles/rich-markdown-editor.css +2 -2
  429. package/package.json +1 -1
@@ -5,6 +5,6 @@ import { IconChevronDown, IconCheck } from "@tabler/icons-react";
5
5
  * Controlled via `open` / `onToggle` for accordion behaviour.
6
6
  */
7
7
  export function SettingsSection({ id, icon, title, subtitle, badge, required, connected, open = false, onToggle, children, }) {
8
- return (_jsxs("div", { id: id, className: "rounded-lg border border-border bg-background/50", children: [_jsxs("button", { type: "button", onClick: onToggle, className: "flex w-full cursor-pointer items-center justify-between px-3 py-2.5 text-left rounded-lg hover:bg-accent/40 transition-colors", children: [_jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [_jsx("span", { className: "shrink-0 text-muted-foreground", children: icon }), _jsx("span", { className: "text-[12px] font-medium text-foreground truncate", children: title }), connected && (_jsx("span", { className: "flex items-center justify-center shrink-0 rounded-full bg-green-500/15 text-green-500 w-4 h-4", children: _jsx(IconCheck, { size: 10, stroke: 3 }) })), required && !connected && (_jsx("span", { className: "shrink-0 rounded-full bg-accent/60 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-muted-foreground", children: "Required" })), badge && (_jsx("span", { className: "shrink-0 rounded-full bg-accent/60 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-muted-foreground", children: badge }))] }), _jsx(IconChevronDown, { size: 12, className: `shrink-0 text-muted-foreground transition-transform ${open ? "rotate-180" : ""}` })] }), open && (_jsxs("div", { className: "border-t border-border px-3 pb-3 pt-2.5", children: [subtitle && (_jsx("p", { className: "text-[10px] text-muted-foreground mb-2.5", children: subtitle })), children] }))] }));
8
+ return (_jsxs("div", { id: id, className: "rounded-lg border border-border bg-background/50", children: [_jsxs("button", { type: "button", onClick: onToggle, className: "flex w-full cursor-pointer items-center justify-between px-3 py-2.5 text-start rounded-lg hover:bg-accent/40 transition-colors", children: [_jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [_jsx("span", { className: "shrink-0 text-muted-foreground", children: icon }), _jsx("span", { className: "text-[12px] font-medium text-foreground truncate", children: title }), connected && (_jsx("span", { className: "flex items-center justify-center shrink-0 rounded-full bg-green-500/15 text-green-500 w-4 h-4", children: _jsx(IconCheck, { size: 10, stroke: 3 }) })), required && !connected && (_jsx("span", { className: "shrink-0 rounded-full bg-accent/60 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-muted-foreground", children: "Required" })), badge && (_jsx("span", { className: "shrink-0 rounded-full bg-accent/60 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-muted-foreground", children: badge }))] }), _jsx(IconChevronDown, { size: 12, className: `shrink-0 text-muted-foreground transition-transform ${open ? "rotate-180" : ""}` })] }), open && (_jsxs("div", { className: "border-t border-border px-3 pb-3 pt-2.5", children: [subtitle && (_jsx("p", { className: "text-[10px] text-muted-foreground mb-2.5", children: subtitle })), children] }))] }));
9
9
  }
10
10
  //# sourceMappingURL=SettingsSection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SettingsSection.js","sourceRoot":"","sources":["../../../src/client/settings/SettingsSection.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAejE;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,EAAE,EACF,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,SAAS,EACT,IAAI,GAAG,KAAK,EACZ,QAAQ,EACR,QAAQ,GACa;IACrB,OAAO,CACL,eAAK,EAAE,EAAE,EAAE,EAAE,SAAS,EAAC,kDAAkD,aACvE,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAC,+HAA+H,aAEzI,eAAK,SAAS,EAAC,iCAAiC,aAC9C,eAAM,SAAS,EAAC,gCAAgC,YAAE,IAAI,GAAQ,EAC9D,eAAM,SAAS,EAAC,kDAAkD,YAC/D,KAAK,GACD,EACN,SAAS,IAAI,CACZ,eAAM,SAAS,EAAC,+FAA+F,YAC7G,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,GAAI,GAC7B,CACR,EACA,QAAQ,IAAI,CAAC,SAAS,IAAI,CACzB,eAAM,SAAS,EAAC,yHAAyH,yBAElI,CACR,EACA,KAAK,IAAI,CACR,eAAM,SAAS,EAAC,yHAAyH,YACtI,KAAK,GACD,CACR,IACG,EACN,KAAC,eAAe,IACd,IAAI,EAAE,EAAE,EACR,SAAS,EAAE,uDAAuD,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,GAC5F,IACK,EACR,IAAI,IAAI,CACP,eAAK,SAAS,EAAC,yCAAyC,aACrD,QAAQ,IAAI,CACX,YAAG,SAAS,EAAC,0CAA0C,YACpD,QAAQ,GACP,CACL,EACA,QAAQ,IACL,CACP,IACG,CACP,CAAC;AACJ,CAAC","sourcesContent":["import type { ReactNode } from \"react\";\nimport { IconChevronDown, IconCheck } from \"@tabler/icons-react\";\n\ninterface SettingsSectionProps {\n id?: string;\n icon: ReactNode;\n title: string;\n subtitle?: string;\n badge?: string;\n required?: boolean;\n connected?: boolean;\n open?: boolean;\n onToggle?: () => void;\n children: ReactNode;\n}\n\n/**\n * Collapsible settings section card with icon, title, status dot, and optional badge.\n * Controlled via `open` / `onToggle` for accordion behaviour.\n */\nexport function SettingsSection({\n id,\n icon,\n title,\n subtitle,\n badge,\n required,\n connected,\n open = false,\n onToggle,\n children,\n}: SettingsSectionProps) {\n return (\n <div id={id} className=\"rounded-lg border border-border bg-background/50\">\n <button\n type=\"button\"\n onClick={onToggle}\n className=\"flex w-full cursor-pointer items-center justify-between px-3 py-2.5 text-left rounded-lg hover:bg-accent/40 transition-colors\"\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <span className=\"shrink-0 text-muted-foreground\">{icon}</span>\n <span className=\"text-[12px] font-medium text-foreground truncate\">\n {title}\n </span>\n {connected && (\n <span className=\"flex items-center justify-center shrink-0 rounded-full bg-green-500/15 text-green-500 w-4 h-4\">\n <IconCheck size={10} stroke={3} />\n </span>\n )}\n {required && !connected && (\n <span className=\"shrink-0 rounded-full bg-accent/60 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-muted-foreground\">\n Required\n </span>\n )}\n {badge && (\n <span className=\"shrink-0 rounded-full bg-accent/60 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-muted-foreground\">\n {badge}\n </span>\n )}\n </div>\n <IconChevronDown\n size={12}\n className={`shrink-0 text-muted-foreground transition-transform ${open ? \"rotate-180\" : \"\"}`}\n />\n </button>\n {open && (\n <div className=\"border-t border-border px-3 pb-3 pt-2.5\">\n {subtitle && (\n <p className=\"text-[10px] text-muted-foreground mb-2.5\">\n {subtitle}\n </p>\n )}\n {children}\n </div>\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"SettingsSection.js","sourceRoot":"","sources":["../../../src/client/settings/SettingsSection.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAejE;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,EAAE,EACF,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,SAAS,EACT,IAAI,GAAG,KAAK,EACZ,QAAQ,EACR,QAAQ,GACa;IACrB,OAAO,CACL,eAAK,EAAE,EAAE,EAAE,EAAE,SAAS,EAAC,kDAAkD,aACvE,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAC,gIAAgI,aAE1I,eAAK,SAAS,EAAC,iCAAiC,aAC9C,eAAM,SAAS,EAAC,gCAAgC,YAAE,IAAI,GAAQ,EAC9D,eAAM,SAAS,EAAC,kDAAkD,YAC/D,KAAK,GACD,EACN,SAAS,IAAI,CACZ,eAAM,SAAS,EAAC,+FAA+F,YAC7G,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,GAAI,GAC7B,CACR,EACA,QAAQ,IAAI,CAAC,SAAS,IAAI,CACzB,eAAM,SAAS,EAAC,yHAAyH,yBAElI,CACR,EACA,KAAK,IAAI,CACR,eAAM,SAAS,EAAC,yHAAyH,YACtI,KAAK,GACD,CACR,IACG,EACN,KAAC,eAAe,IACd,IAAI,EAAE,EAAE,EACR,SAAS,EAAE,uDAAuD,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,GAC5F,IACK,EACR,IAAI,IAAI,CACP,eAAK,SAAS,EAAC,yCAAyC,aACrD,QAAQ,IAAI,CACX,YAAG,SAAS,EAAC,0CAA0C,YACpD,QAAQ,GACP,CACL,EACA,QAAQ,IACL,CACP,IACG,CACP,CAAC;AACJ,CAAC","sourcesContent":["import type { ReactNode } from \"react\";\nimport { IconChevronDown, IconCheck } from \"@tabler/icons-react\";\n\ninterface SettingsSectionProps {\n id?: string;\n icon: ReactNode;\n title: string;\n subtitle?: string;\n badge?: string;\n required?: boolean;\n connected?: boolean;\n open?: boolean;\n onToggle?: () => void;\n children: ReactNode;\n}\n\n/**\n * Collapsible settings section card with icon, title, status dot, and optional badge.\n * Controlled via `open` / `onToggle` for accordion behaviour.\n */\nexport function SettingsSection({\n id,\n icon,\n title,\n subtitle,\n badge,\n required,\n connected,\n open = false,\n onToggle,\n children,\n}: SettingsSectionProps) {\n return (\n <div id={id} className=\"rounded-lg border border-border bg-background/50\">\n <button\n type=\"button\"\n onClick={onToggle}\n className=\"flex w-full cursor-pointer items-center justify-between px-3 py-2.5 text-start rounded-lg hover:bg-accent/40 transition-colors\"\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <span className=\"shrink-0 text-muted-foreground\">{icon}</span>\n <span className=\"text-[12px] font-medium text-foreground truncate\">\n {title}\n </span>\n {connected && (\n <span className=\"flex items-center justify-center shrink-0 rounded-full bg-green-500/15 text-green-500 w-4 h-4\">\n <IconCheck size={10} stroke={3} />\n </span>\n )}\n {required && !connected && (\n <span className=\"shrink-0 rounded-full bg-accent/60 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-muted-foreground\">\n Required\n </span>\n )}\n {badge && (\n <span className=\"shrink-0 rounded-full bg-accent/60 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-muted-foreground\">\n {badge}\n </span>\n )}\n </div>\n <IconChevronDown\n size={12}\n className={`shrink-0 text-muted-foreground transition-transform ${open ? \"rotate-180\" : \"\"}`}\n />\n </button>\n {open && (\n <div className=\"border-t border-border px-3 pb-3 pt-2.5\">\n {subtitle && (\n <p className=\"text-[10px] text-muted-foreground mb-2.5\">\n {subtitle}\n </p>\n )}\n {children}\n </div>\n )}\n </div>\n );\n}\n"]}
@@ -56,7 +56,7 @@ function BucketBars({ buckets, emptyMessage, billing, }) {
56
56
  return (_jsx("p", { className: "text-[10px] text-muted-foreground py-1.5", children: emptyMessage }));
57
57
  }
58
58
  const max = Math.max(...buckets.map((b) => displayAmountFromCostCents(b.cents, billing)), 0.0001);
59
- return (_jsx("div", { className: "space-y-1", children: buckets.map((b) => (_jsxs("div", { className: "text-[10px]", children: [_jsxs("div", { className: "flex items-center justify-between gap-2 mb-0.5", children: [_jsx("span", { className: "truncate text-foreground", title: b.key || "(none)", children: b.key || "(none)" }), _jsxs("span", { className: "shrink-0 text-muted-foreground tabular-nums", children: [formatSpend(b.cents, billing), _jsxs("span", { className: "ml-1 opacity-60", children: ["\u00B7 ", formatTokens(b.inputTokens + b.outputTokens), " tok"] })] })] }), _jsx("div", { className: "h-1 rounded-full bg-accent/40 overflow-hidden", children: _jsx("div", { className: "h-full bg-foreground/70", style: {
59
+ return (_jsx("div", { className: "space-y-1", children: buckets.map((b) => (_jsxs("div", { className: "text-[10px]", children: [_jsxs("div", { className: "flex items-center justify-between gap-2 mb-0.5", children: [_jsx("span", { className: "truncate text-foreground", title: b.key || "(none)", children: b.key || "(none)" }), _jsxs("span", { className: "shrink-0 text-muted-foreground tabular-nums", children: [formatSpend(b.cents, billing), _jsxs("span", { className: "ms-1 opacity-60", children: ["\u00B7 ", formatTokens(b.inputTokens + b.outputTokens), " tok"] })] })] }), _jsx("div", { className: "h-1 rounded-full bg-accent/40 overflow-hidden", children: _jsx("div", { className: "h-full bg-foreground/70", style: {
60
60
  width: `${(displayAmountFromCostCents(b.cents, billing) / max) * 100}%`,
61
61
  } }) })] }, b.key))) }));
62
62
  }
@@ -99,6 +99,6 @@ export function UsageSection() {
99
99
  ? "bg-accent text-foreground"
100
100
  : "text-muted-foreground hover:text-foreground"}`, children: r.label }, r.value))) }), _jsx("button", { onClick: () => load(days), className: "flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground", disabled: loading, children: loading ? (_jsx(IconLoader2, { size: 11, className: "animate-spin" })) : (_jsx(IconRefresh, { size: 11 })) })] }), error && _jsx("p", { className: "text-[10px] text-red-500", children: error }), data && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "rounded-md border border-border px-2.5 py-2", children: [_jsxs("div", { className: "flex items-baseline justify-between", children: [_jsxs("div", { children: [_jsx("div", { className: "text-[10px] text-muted-foreground", children: billing.unit === "builder-credits"
101
101
  ? "Builder.io credit spend"
102
- : "Total spend" }), _jsx("div", { className: "text-[18px] font-semibold tabular-nums", children: formatSpend(data.totalCents, billing) })] }), _jsxs("div", { className: "text-right", children: [_jsxs("div", { className: "text-[10px] text-muted-foreground", children: [data.totalCalls, " calls"] }), _jsxs("div", { className: "text-[10px] text-muted-foreground", children: [formatTokens(data.totalInputTokens), " in \u00B7", " ", formatTokens(data.totalOutputTokens), " out"] }), data.totalCacheReadTokens > 0 && (_jsxs("div", { className: "text-[10px] text-green-500/80", children: [formatTokens(data.totalCacheReadTokens), " cached"] }))] })] }), _jsx(DailySparkline, { days: data.byDay, billing: billing })] }), _jsxs("div", { children: [_jsx("div", { className: "text-[10px] font-medium text-foreground mb-1", children: "By label" }), _jsx(BucketBars, { buckets: data.byLabel, emptyMessage: "No labeled calls yet.", billing: billing })] }), _jsxs("div", { children: [_jsx("div", { className: "text-[10px] font-medium text-foreground mb-1", children: "By model" }), _jsx(BucketBars, { buckets: data.byModel, emptyMessage: "No calls recorded.", billing: billing })] }), data.byApp.filter((b) => b.key).length > 1 && (_jsxs("div", { children: [_jsx("div", { className: "text-[10px] font-medium text-foreground mb-1", children: "By app" }), _jsx(BucketBars, { buckets: data.byApp, emptyMessage: "", billing: billing })] })), data.recent.length > 0 && (_jsxs("details", { children: [_jsxs("summary", { className: "text-[10px] font-medium text-foreground cursor-pointer select-none hover:text-foreground/80", children: ["Recent calls (", data.recent.length, ")"] }), _jsx("div", { className: "mt-1.5 max-h-48 overflow-y-auto space-y-0.5 rounded border border-border", children: data.recent.map((r) => (_jsxs("div", { className: "flex items-center justify-between gap-2 px-2 py-1 text-[10px] border-b border-border last:border-b-0", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "truncate text-foreground", title: r.label, children: [r.label, r.app ? (_jsxs("span", { className: "text-muted-foreground", children: [" ", "\u00B7 ", r.app] })) : null] }), _jsxs("div", { className: "truncate text-muted-foreground", children: [new Date(r.createdAt).toLocaleString(), " \u00B7 ", r.model] })] }), _jsx("div", { className: "shrink-0 text-right tabular-nums text-muted-foreground", children: formatSpend(r.cents, billing) })] }, r.id))) })] })), billing.unit === "builder-credits" ? (_jsxs("p", { className: "text-[10px] text-muted-foreground", children: ["Builder.io credits are estimated from hard token cost, a", " ", billing.hardCostMarginMultiplier ?? 1.25, "x margin, and", " ", billing.creditsPerUsd ?? 20, " credits per dollar."] })) : (_jsx("p", { className: "text-[10px] text-muted-foreground", children: "Spend is estimated from published Anthropic pricing and your own recorded token counts. Cached input is priced at ~10% of regular input." }))] }))] }));
102
+ : "Total spend" }), _jsx("div", { className: "text-[18px] font-semibold tabular-nums", children: formatSpend(data.totalCents, billing) })] }), _jsxs("div", { className: "text-end", children: [_jsxs("div", { className: "text-[10px] text-muted-foreground", children: [data.totalCalls, " calls"] }), _jsxs("div", { className: "text-[10px] text-muted-foreground", children: [formatTokens(data.totalInputTokens), " in \u00B7", " ", formatTokens(data.totalOutputTokens), " out"] }), data.totalCacheReadTokens > 0 && (_jsxs("div", { className: "text-[10px] text-green-500/80", children: [formatTokens(data.totalCacheReadTokens), " cached"] }))] })] }), _jsx(DailySparkline, { days: data.byDay, billing: billing })] }), _jsxs("div", { children: [_jsx("div", { className: "text-[10px] font-medium text-foreground mb-1", children: "By label" }), _jsx(BucketBars, { buckets: data.byLabel, emptyMessage: "No labeled calls yet.", billing: billing })] }), _jsxs("div", { children: [_jsx("div", { className: "text-[10px] font-medium text-foreground mb-1", children: "By model" }), _jsx(BucketBars, { buckets: data.byModel, emptyMessage: "No calls recorded.", billing: billing })] }), data.byApp.filter((b) => b.key).length > 1 && (_jsxs("div", { children: [_jsx("div", { className: "text-[10px] font-medium text-foreground mb-1", children: "By app" }), _jsx(BucketBars, { buckets: data.byApp, emptyMessage: "", billing: billing })] })), data.recent.length > 0 && (_jsxs("details", { children: [_jsxs("summary", { className: "text-[10px] font-medium text-foreground cursor-pointer select-none hover:text-foreground/80", children: ["Recent calls (", data.recent.length, ")"] }), _jsx("div", { className: "mt-1.5 max-h-48 overflow-y-auto space-y-0.5 rounded border border-border", children: data.recent.map((r) => (_jsxs("div", { className: "flex items-center justify-between gap-2 px-2 py-1 text-[10px] border-b border-border last:border-b-0", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "truncate text-foreground", title: r.label, children: [r.label, r.app ? (_jsxs("span", { className: "text-muted-foreground", children: [" ", "\u00B7 ", r.app] })) : null] }), _jsxs("div", { className: "truncate text-muted-foreground", children: [new Date(r.createdAt).toLocaleString(), " \u00B7 ", r.model] })] }), _jsx("div", { className: "shrink-0 text-end tabular-nums text-muted-foreground", children: formatSpend(r.cents, billing) })] }, r.id))) })] })), billing.unit === "builder-credits" ? (_jsxs("p", { className: "text-[10px] text-muted-foreground", children: ["Builder.io credits are estimated from hard token cost, a", " ", billing.hardCostMarginMultiplier ?? 1.25, "x margin, and", " ", billing.creditsPerUsd ?? 20, " credits per dollar."] })) : (_jsx("p", { className: "text-[10px] text-muted-foreground", children: "Spend is estimated from published Anthropic pricing and your own recorded token counts. Cached input is priced at ~10% of regular input." }))] }))] }));
103
103
  }
104
104
  //# sourceMappingURL=UsageSection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"UsageSection.js","sourceRoot":"","sources":["../../../src/client/settings/UsageSection.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport { useEffect, useState } from \"react\";\nimport { IconLoader2, IconRefresh } from \"@tabler/icons-react\";\n\ninterface UsageBucket {\n key: string;\n cents: number;\n calls: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n}\n\ninterface DailyBucket {\n date: string;\n cents: number;\n calls: number;\n}\n\ninterface UsageRecentEntry {\n id: number;\n createdAt: number;\n label: string;\n app: string;\n model: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n cents: number;\n}\n\ninterface UsageBillingMode {\n unit: \"usd\" | \"builder-credits\";\n label: string;\n shortLabel: string;\n source: \"estimated-provider-cost\" | \"builder-agent-credits\";\n hardCostMarginMultiplier?: number;\n creditsPerUsd?: number;\n}\n\ninterface UsageSummary {\n billing?: UsageBillingMode;\n totalCents: number;\n totalCalls: number;\n totalInputTokens: number;\n totalOutputTokens: number;\n totalCacheReadTokens: number;\n totalCacheWriteTokens: number;\n sinceMs: number;\n byLabel: UsageBucket[];\n byModel: UsageBucket[];\n byApp: UsageBucket[];\n byDay: DailyBucket[];\n recent: UsageRecentEntry[];\n}\n\nconst RANGES = [\n { value: 1, label: \"24h\" },\n { value: 7, label: \"7d\" },\n { value: 30, label: \"30d\" },\n { value: 90, label: \"90d\" },\n];\n\nconst USD_BILLING: UsageBillingMode = {\n unit: \"usd\",\n label: \"Estimated spend\",\n shortLabel: \"Cost\",\n source: \"estimated-provider-cost\",\n};\n\nfunction displayAmountFromCostCents(\n cents: number,\n billing: UsageBillingMode,\n): number {\n if (billing.unit !== \"builder-credits\") return cents;\n const margin = billing.hardCostMarginMultiplier ?? 1.25;\n const creditsPerUsd = billing.creditsPerUsd ?? 20;\n const credits = (cents / 100) * margin * creditsPerUsd;\n return credits <= 0 ? 0 : Math.ceil(credits * 1000) / 1000;\n}\n\nfunction formatCredits(credits: number): string {\n if (!Number.isFinite(credits) || credits === 0) return \"0 credits\";\n const maximumFractionDigits = credits < 1 ? 3 : credits < 10 ? 2 : 1;\n const value = credits.toLocaleString(undefined, {\n maximumFractionDigits,\n });\n return `${value} ${credits === 1 ? \"credit\" : \"credits\"}`;\n}\n\nfunction formatSpend(cents: number, billing: UsageBillingMode): string {\n if (billing.unit === \"builder-credits\") {\n return formatCredits(displayAmountFromCostCents(cents, billing));\n }\n // Sub-cent values (e.g. a single LLM call at $0.0045 = 0.45¢) — keep\n // three decimals so tiny calls don't round to 0.00¢. The prior impl\n // multiplied by 100 in this branch, overstating small costs 100×.\n if (cents < 1) return `${cents.toFixed(3)}¢`;\n if (cents < 100) return `${cents.toFixed(2)}¢`;\n return `$${(cents / 100).toFixed(2)}`;\n}\n\nfunction formatTokens(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return String(n);\n}\n\nfunction BucketBars({\n buckets,\n emptyMessage,\n billing,\n}: {\n buckets: UsageBucket[];\n emptyMessage: string;\n billing: UsageBillingMode;\n}) {\n if (buckets.length === 0) {\n return (\n <p className=\"text-[10px] text-muted-foreground py-1.5\">{emptyMessage}</p>\n );\n }\n const max = Math.max(\n ...buckets.map((b) => displayAmountFromCostCents(b.cents, billing)),\n 0.0001,\n );\n return (\n <div className=\"space-y-1\">\n {buckets.map((b) => (\n <div key={b.key} className=\"text-[10px]\">\n <div className=\"flex items-center justify-between gap-2 mb-0.5\">\n <span\n className=\"truncate text-foreground\"\n title={b.key || \"(none)\"}\n >\n {b.key || \"(none)\"}\n </span>\n <span className=\"shrink-0 text-muted-foreground tabular-nums\">\n {formatSpend(b.cents, billing)}\n <span className=\"ml-1 opacity-60\">\n · {formatTokens(b.inputTokens + b.outputTokens)} tok\n </span>\n </span>\n </div>\n <div className=\"h-1 rounded-full bg-accent/40 overflow-hidden\">\n <div\n className=\"h-full bg-foreground/70\"\n style={{\n width: `${(displayAmountFromCostCents(b.cents, billing) / max) * 100}%`,\n }}\n />\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction DailySparkline({\n days,\n billing,\n}: {\n days: DailyBucket[];\n billing: UsageBillingMode;\n}) {\n if (days.length === 0) return null;\n const max = Math.max(\n ...days.map((d) => displayAmountFromCostCents(d.cents, billing)),\n 0.0001,\n );\n return (\n <div className=\"flex items-end gap-[2px] h-8 pt-2\">\n {days.map((d) => (\n <div\n key={d.date}\n className=\"flex-1 bg-foreground/60 rounded-sm min-h-[1px]\"\n style={{\n height: `${Math.max(\n 2,\n (displayAmountFromCostCents(d.cents, billing) / max) * 100,\n )}%`,\n }}\n title={`${d.date}: ${formatSpend(d.cents, billing)} (${d.calls} calls)`}\n />\n ))}\n </div>\n );\n}\n\nexport function UsageSection() {\n const [days, setDays] = useState(30);\n const [data, setData] = useState<UsageSummary | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const billing = data?.billing ?? USD_BILLING;\n\n const load = async (rangeDays: number) => {\n setLoading(true);\n setError(null);\n try {\n const res = await fetch(\n agentNativePath(`/_agent-native/usage?sinceDays=${rangeDays}`),\n );\n if (!res.ok) {\n throw new Error(`Failed (${res.status})`);\n }\n const json = (await res.json()) as UsageSummary;\n setData(json);\n } catch (err: any) {\n setError(err?.message || \"Failed to load usage\");\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n load(days);\n }, [days]);\n\n return (\n <div className=\"space-y-3\">\n {/* Range selector + refresh */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex gap-1 rounded-md border border-border p-0.5\">\n {RANGES.map((r) => (\n <button\n key={r.value}\n onClick={() => setDays(r.value)}\n className={`px-2 py-0.5 text-[10px] rounded ${\n days === r.value\n ? \"bg-accent text-foreground\"\n : \"text-muted-foreground hover:text-foreground\"\n }`}\n >\n {r.label}\n </button>\n ))}\n </div>\n <button\n onClick={() => load(days)}\n className=\"flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground\"\n disabled={loading}\n >\n {loading ? (\n <IconLoader2 size={11} className=\"animate-spin\" />\n ) : (\n <IconRefresh size={11} />\n )}\n </button>\n </div>\n\n {error && <p className=\"text-[10px] text-red-500\">{error}</p>}\n\n {data && (\n <>\n {/* Totals */}\n <div className=\"rounded-md border border-border px-2.5 py-2\">\n <div className=\"flex items-baseline justify-between\">\n <div>\n <div className=\"text-[10px] text-muted-foreground\">\n {billing.unit === \"builder-credits\"\n ? \"Builder.io credit spend\"\n : \"Total spend\"}\n </div>\n <div className=\"text-[18px] font-semibold tabular-nums\">\n {formatSpend(data.totalCents, billing)}\n </div>\n </div>\n <div className=\"text-right\">\n <div className=\"text-[10px] text-muted-foreground\">\n {data.totalCalls} calls\n </div>\n <div className=\"text-[10px] text-muted-foreground\">\n {formatTokens(data.totalInputTokens)} in ·{\" \"}\n {formatTokens(data.totalOutputTokens)} out\n </div>\n {data.totalCacheReadTokens > 0 && (\n <div className=\"text-[10px] text-green-500/80\">\n {formatTokens(data.totalCacheReadTokens)} cached\n </div>\n )}\n </div>\n </div>\n <DailySparkline days={data.byDay} billing={billing} />\n </div>\n\n {/* By label */}\n <div>\n <div className=\"text-[10px] font-medium text-foreground mb-1\">\n By label\n </div>\n <BucketBars\n buckets={data.byLabel}\n emptyMessage=\"No labeled calls yet.\"\n billing={billing}\n />\n </div>\n\n {/* By model */}\n <div>\n <div className=\"text-[10px] font-medium text-foreground mb-1\">\n By model\n </div>\n <BucketBars\n buckets={data.byModel}\n emptyMessage=\"No calls recorded.\"\n billing={billing}\n />\n </div>\n\n {/* By app — only show when multiple apps contribute */}\n {data.byApp.filter((b) => b.key).length > 1 && (\n <div>\n <div className=\"text-[10px] font-medium text-foreground mb-1\">\n By app\n </div>\n <BucketBars\n buckets={data.byApp}\n emptyMessage=\"\"\n billing={billing}\n />\n </div>\n )}\n\n {/* Recent calls */}\n {data.recent.length > 0 && (\n <details>\n <summary className=\"text-[10px] font-medium text-foreground cursor-pointer select-none hover:text-foreground/80\">\n Recent calls ({data.recent.length})\n </summary>\n <div className=\"mt-1.5 max-h-48 overflow-y-auto space-y-0.5 rounded border border-border\">\n {data.recent.map((r) => (\n <div\n key={r.id}\n className=\"flex items-center justify-between gap-2 px-2 py-1 text-[10px] border-b border-border last:border-b-0\"\n >\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-foreground\" title={r.label}>\n {r.label}\n {r.app ? (\n <span className=\"text-muted-foreground\">\n {\" \"}\n · {r.app}\n </span>\n ) : null}\n </div>\n <div className=\"truncate text-muted-foreground\">\n {new Date(r.createdAt).toLocaleString()} · {r.model}\n </div>\n </div>\n <div className=\"shrink-0 text-right tabular-nums text-muted-foreground\">\n {formatSpend(r.cents, billing)}\n </div>\n </div>\n ))}\n </div>\n </details>\n )}\n\n {billing.unit === \"builder-credits\" ? (\n <p className=\"text-[10px] text-muted-foreground\">\n Builder.io credits are estimated from hard token cost, a{\" \"}\n {billing.hardCostMarginMultiplier ?? 1.25}x margin, and{\" \"}\n {billing.creditsPerUsd ?? 20} credits per dollar.\n </p>\n ) : (\n <p className=\"text-[10px] text-muted-foreground\">\n Spend is estimated from published Anthropic pricing and your own\n recorded token counts. Cached input is priced at ~10% of regular\n input.\n </p>\n )}\n </>\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"UsageSection.js","sourceRoot":"","sources":["../../../src/client/settings/UsageSection.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath } from \"../api-path.js\";\nimport { useEffect, useState } from \"react\";\nimport { IconLoader2, IconRefresh } from \"@tabler/icons-react\";\n\ninterface UsageBucket {\n key: string;\n cents: number;\n calls: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n}\n\ninterface DailyBucket {\n date: string;\n cents: number;\n calls: number;\n}\n\ninterface UsageRecentEntry {\n id: number;\n createdAt: number;\n label: string;\n app: string;\n model: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n cents: number;\n}\n\ninterface UsageBillingMode {\n unit: \"usd\" | \"builder-credits\";\n label: string;\n shortLabel: string;\n source: \"estimated-provider-cost\" | \"builder-agent-credits\";\n hardCostMarginMultiplier?: number;\n creditsPerUsd?: number;\n}\n\ninterface UsageSummary {\n billing?: UsageBillingMode;\n totalCents: number;\n totalCalls: number;\n totalInputTokens: number;\n totalOutputTokens: number;\n totalCacheReadTokens: number;\n totalCacheWriteTokens: number;\n sinceMs: number;\n byLabel: UsageBucket[];\n byModel: UsageBucket[];\n byApp: UsageBucket[];\n byDay: DailyBucket[];\n recent: UsageRecentEntry[];\n}\n\nconst RANGES = [\n { value: 1, label: \"24h\" },\n { value: 7, label: \"7d\" },\n { value: 30, label: \"30d\" },\n { value: 90, label: \"90d\" },\n];\n\nconst USD_BILLING: UsageBillingMode = {\n unit: \"usd\",\n label: \"Estimated spend\",\n shortLabel: \"Cost\",\n source: \"estimated-provider-cost\",\n};\n\nfunction displayAmountFromCostCents(\n cents: number,\n billing: UsageBillingMode,\n): number {\n if (billing.unit !== \"builder-credits\") return cents;\n const margin = billing.hardCostMarginMultiplier ?? 1.25;\n const creditsPerUsd = billing.creditsPerUsd ?? 20;\n const credits = (cents / 100) * margin * creditsPerUsd;\n return credits <= 0 ? 0 : Math.ceil(credits * 1000) / 1000;\n}\n\nfunction formatCredits(credits: number): string {\n if (!Number.isFinite(credits) || credits === 0) return \"0 credits\";\n const maximumFractionDigits = credits < 1 ? 3 : credits < 10 ? 2 : 1;\n const value = credits.toLocaleString(undefined, {\n maximumFractionDigits,\n });\n return `${value} ${credits === 1 ? \"credit\" : \"credits\"}`;\n}\n\nfunction formatSpend(cents: number, billing: UsageBillingMode): string {\n if (billing.unit === \"builder-credits\") {\n return formatCredits(displayAmountFromCostCents(cents, billing));\n }\n // Sub-cent values (e.g. a single LLM call at $0.0045 = 0.45¢) — keep\n // three decimals so tiny calls don't round to 0.00¢. The prior impl\n // multiplied by 100 in this branch, overstating small costs 100×.\n if (cents < 1) return `${cents.toFixed(3)}¢`;\n if (cents < 100) return `${cents.toFixed(2)}¢`;\n return `$${(cents / 100).toFixed(2)}`;\n}\n\nfunction formatTokens(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return String(n);\n}\n\nfunction BucketBars({\n buckets,\n emptyMessage,\n billing,\n}: {\n buckets: UsageBucket[];\n emptyMessage: string;\n billing: UsageBillingMode;\n}) {\n if (buckets.length === 0) {\n return (\n <p className=\"text-[10px] text-muted-foreground py-1.5\">{emptyMessage}</p>\n );\n }\n const max = Math.max(\n ...buckets.map((b) => displayAmountFromCostCents(b.cents, billing)),\n 0.0001,\n );\n return (\n <div className=\"space-y-1\">\n {buckets.map((b) => (\n <div key={b.key} className=\"text-[10px]\">\n <div className=\"flex items-center justify-between gap-2 mb-0.5\">\n <span\n className=\"truncate text-foreground\"\n title={b.key || \"(none)\"}\n >\n {b.key || \"(none)\"}\n </span>\n <span className=\"shrink-0 text-muted-foreground tabular-nums\">\n {formatSpend(b.cents, billing)}\n <span className=\"ms-1 opacity-60\">\n · {formatTokens(b.inputTokens + b.outputTokens)} tok\n </span>\n </span>\n </div>\n <div className=\"h-1 rounded-full bg-accent/40 overflow-hidden\">\n <div\n className=\"h-full bg-foreground/70\"\n style={{\n width: `${(displayAmountFromCostCents(b.cents, billing) / max) * 100}%`,\n }}\n />\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction DailySparkline({\n days,\n billing,\n}: {\n days: DailyBucket[];\n billing: UsageBillingMode;\n}) {\n if (days.length === 0) return null;\n const max = Math.max(\n ...days.map((d) => displayAmountFromCostCents(d.cents, billing)),\n 0.0001,\n );\n return (\n <div className=\"flex items-end gap-[2px] h-8 pt-2\">\n {days.map((d) => (\n <div\n key={d.date}\n className=\"flex-1 bg-foreground/60 rounded-sm min-h-[1px]\"\n style={{\n height: `${Math.max(\n 2,\n (displayAmountFromCostCents(d.cents, billing) / max) * 100,\n )}%`,\n }}\n title={`${d.date}: ${formatSpend(d.cents, billing)} (${d.calls} calls)`}\n />\n ))}\n </div>\n );\n}\n\nexport function UsageSection() {\n const [days, setDays] = useState(30);\n const [data, setData] = useState<UsageSummary | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const billing = data?.billing ?? USD_BILLING;\n\n const load = async (rangeDays: number) => {\n setLoading(true);\n setError(null);\n try {\n const res = await fetch(\n agentNativePath(`/_agent-native/usage?sinceDays=${rangeDays}`),\n );\n if (!res.ok) {\n throw new Error(`Failed (${res.status})`);\n }\n const json = (await res.json()) as UsageSummary;\n setData(json);\n } catch (err: any) {\n setError(err?.message || \"Failed to load usage\");\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n load(days);\n }, [days]);\n\n return (\n <div className=\"space-y-3\">\n {/* Range selector + refresh */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex gap-1 rounded-md border border-border p-0.5\">\n {RANGES.map((r) => (\n <button\n key={r.value}\n onClick={() => setDays(r.value)}\n className={`px-2 py-0.5 text-[10px] rounded ${\n days === r.value\n ? \"bg-accent text-foreground\"\n : \"text-muted-foreground hover:text-foreground\"\n }`}\n >\n {r.label}\n </button>\n ))}\n </div>\n <button\n onClick={() => load(days)}\n className=\"flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground\"\n disabled={loading}\n >\n {loading ? (\n <IconLoader2 size={11} className=\"animate-spin\" />\n ) : (\n <IconRefresh size={11} />\n )}\n </button>\n </div>\n\n {error && <p className=\"text-[10px] text-red-500\">{error}</p>}\n\n {data && (\n <>\n {/* Totals */}\n <div className=\"rounded-md border border-border px-2.5 py-2\">\n <div className=\"flex items-baseline justify-between\">\n <div>\n <div className=\"text-[10px] text-muted-foreground\">\n {billing.unit === \"builder-credits\"\n ? \"Builder.io credit spend\"\n : \"Total spend\"}\n </div>\n <div className=\"text-[18px] font-semibold tabular-nums\">\n {formatSpend(data.totalCents, billing)}\n </div>\n </div>\n <div className=\"text-end\">\n <div className=\"text-[10px] text-muted-foreground\">\n {data.totalCalls} calls\n </div>\n <div className=\"text-[10px] text-muted-foreground\">\n {formatTokens(data.totalInputTokens)} in ·{\" \"}\n {formatTokens(data.totalOutputTokens)} out\n </div>\n {data.totalCacheReadTokens > 0 && (\n <div className=\"text-[10px] text-green-500/80\">\n {formatTokens(data.totalCacheReadTokens)} cached\n </div>\n )}\n </div>\n </div>\n <DailySparkline days={data.byDay} billing={billing} />\n </div>\n\n {/* By label */}\n <div>\n <div className=\"text-[10px] font-medium text-foreground mb-1\">\n By label\n </div>\n <BucketBars\n buckets={data.byLabel}\n emptyMessage=\"No labeled calls yet.\"\n billing={billing}\n />\n </div>\n\n {/* By model */}\n <div>\n <div className=\"text-[10px] font-medium text-foreground mb-1\">\n By model\n </div>\n <BucketBars\n buckets={data.byModel}\n emptyMessage=\"No calls recorded.\"\n billing={billing}\n />\n </div>\n\n {/* By app — only show when multiple apps contribute */}\n {data.byApp.filter((b) => b.key).length > 1 && (\n <div>\n <div className=\"text-[10px] font-medium text-foreground mb-1\">\n By app\n </div>\n <BucketBars\n buckets={data.byApp}\n emptyMessage=\"\"\n billing={billing}\n />\n </div>\n )}\n\n {/* Recent calls */}\n {data.recent.length > 0 && (\n <details>\n <summary className=\"text-[10px] font-medium text-foreground cursor-pointer select-none hover:text-foreground/80\">\n Recent calls ({data.recent.length})\n </summary>\n <div className=\"mt-1.5 max-h-48 overflow-y-auto space-y-0.5 rounded border border-border\">\n {data.recent.map((r) => (\n <div\n key={r.id}\n className=\"flex items-center justify-between gap-2 px-2 py-1 text-[10px] border-b border-border last:border-b-0\"\n >\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-foreground\" title={r.label}>\n {r.label}\n {r.app ? (\n <span className=\"text-muted-foreground\">\n {\" \"}\n · {r.app}\n </span>\n ) : null}\n </div>\n <div className=\"truncate text-muted-foreground\">\n {new Date(r.createdAt).toLocaleString()} · {r.model}\n </div>\n </div>\n <div className=\"shrink-0 text-end tabular-nums text-muted-foreground\">\n {formatSpend(r.cents, billing)}\n </div>\n </div>\n ))}\n </div>\n </details>\n )}\n\n {billing.unit === \"builder-credits\" ? (\n <p className=\"text-[10px] text-muted-foreground\">\n Builder.io credits are estimated from hard token cost, a{\" \"}\n {billing.hardCostMarginMultiplier ?? 1.25}x margin, and{\" \"}\n {billing.creditsPerUsd ?? 20} credits per dollar.\n </p>\n ) : (\n <p className=\"text-[10px] text-muted-foreground\">\n Spend is estimated from published Anthropic pricing and your own\n recorded token counts. Cached input is priced at ~10% of regular\n input.\n </p>\n )}\n </>\n )}\n </div>\n );\n}\n"]}
@@ -285,7 +285,7 @@ export function VoiceTranscriptionSection() {
285
285
  ? "Builder ready"
286
286
  : geminiConfigured
287
287
  ? "Gemini key set"
288
- : "Needs key" }))] })] }), _jsxs("div", { className: "rounded-md border border-border bg-background", children: [_jsxs("button", { type: "button", onClick: () => setShowAdvanced((v) => !v), className: "w-full flex items-center justify-between gap-2 px-2.5 py-2 cursor-pointer", children: [_jsxs("span", { className: "text-[11px] font-medium text-foreground inline-flex items-center gap-1", children: [showAdvanced ? (_jsx(IconChevronDown, { size: 12 })) : (_jsx(IconChevronRight, { size: 12 })), "Add API keys"] }), _jsx("span", { className: "text-[10px] text-muted-foreground", children: "Google STT \u00B7 Gemini \u00B7 Groq \u00B7 OpenAI" })] }), showAdvanced && (_jsxs("div", { className: "px-2 pb-2 space-y-2", children: [_jsx(ProviderOption, { id: "google-service-account", selected: transcriptionMode === "google-realtime", onSelect: () => chooseSource("google-realtime"), disabled: !googleRealtimeReady, title: "Google Speech-to-Text service account", subtitle: googleRealtimeConfigured
288
+ : "Needs key" }))] })] }), _jsxs("div", { className: "rounded-md border border-border bg-background", children: [_jsxs("button", { type: "button", onClick: () => setShowAdvanced((v) => !v), className: "w-full flex items-center justify-between gap-2 px-2.5 py-2 cursor-pointer", children: [_jsxs("span", { className: "text-[11px] font-medium text-foreground inline-flex items-center gap-1", children: [showAdvanced ? (_jsx(IconChevronDown, { size: 12 })) : (_jsx(IconChevronRight, { size: 12, className: "rtl:-scale-x-100" })), "Add API keys"] }), _jsx("span", { className: "text-[10px] text-muted-foreground", children: "Google STT \u00B7 Gemini \u00B7 Groq \u00B7 OpenAI" })] }), showAdvanced && (_jsxs("div", { className: "px-2 pb-2 space-y-2", children: [_jsx(ProviderOption, { id: "google-service-account", selected: transcriptionMode === "google-realtime", onSelect: () => chooseSource("google-realtime"), disabled: !googleRealtimeReady, title: "Google Speech-to-Text service account", subtitle: googleRealtimeConfigured
289
289
  ? "Service-account JSON is set. Connect Builder to mint the managed realtime WebSocket session."
290
290
  : "Service-account JSON for the dedicated realtime WebSocket to Google StreamingRecognize.", rightSlot: googleRealtimeConfigured ===
291
291
  null ? null : googleRealtimeReady ? (_jsxs("span", { className: "flex items-center gap-1 text-[10px] text-green-500", children: [_jsx(IconCheck, { size: 10 }), "Ready"] })) : googleRealtimeConfigured ? (_jsxs("button", { type: "button", onClick: (e) => {
@@ -325,7 +325,7 @@ function ProviderOption({ id: _id, selected, disabled, onSelect, title, subtitle
325
325
  };
326
326
  return (_jsxs("div", { role: "button", tabIndex: disabled ? -1 : 0, onClick: select, onKeyDown: onKeyDown, "aria-pressed": selected, "aria-disabled": disabled || undefined,
327
327
  // Theme tokens; streaming agent owns layout.
328
- className: `w-full text-left rounded-md border px-2.5 py-2 flex items-start gap-2 ${selected
328
+ className: `w-full text-start rounded-md border px-2.5 py-2 flex items-start gap-2 ${selected
329
329
  ? "border-primary bg-primary/10"
330
330
  : "border-border bg-accent/30 hover:bg-accent/50"} ${disabled ? "opacity-60 cursor-not-allowed" : ""}`, children: [_jsx("span", { className: `mt-[2px] shrink-0 flex h-3.5 w-3.5 items-center justify-center rounded-full border ${selected
331
331
  ? "border-primary bg-primary"
@@ -424,7 +424,7 @@ function SystemAudioStatus() {
424
424
  return (_jsxs("div", { className: "flex items-center gap-1.5 px-0.5 pt-1 text-[10px] text-muted-foreground", children: [_jsx("span", { className: "inline-block h-1.5 w-1.5 shrink-0 rounded-full bg-red-500", "aria-hidden": true }), _jsx("span", { children: "System audio requires macOS 13 or later \u2014 meetings will use mic-only." })] }));
425
425
  }
426
426
  // denied
427
- return (_jsxs("div", { className: "flex items-start gap-1.5 px-0.5 pt-1 text-[10px] text-muted-foreground", children: [_jsx(IconAlertCircle, { size: 11, className: "mt-[1px] shrink-0 text-amber-500" }), _jsxs("div", { className: "flex-1", children: [_jsx("span", { children: "Grant Screen Recording permission in System Settings -> Privacy." }), _jsxs("button", { type: "button", onClick: openPrivacy, className: "ml-1 inline-flex items-center gap-1 rounded border border-border px-1.5 py-0.5 text-[10px] text-muted-foreground hover:bg-accent/40 hover:text-foreground", children: [_jsx(IconLockOpen, { size: 10 }), "Open System Settings"] })] })] }));
427
+ return (_jsxs("div", { className: "flex items-start gap-1.5 px-0.5 pt-1 text-[10px] text-muted-foreground", children: [_jsx(IconAlertCircle, { size: 11, className: "mt-[1px] shrink-0 text-amber-500" }), _jsxs("div", { className: "flex-1", children: [_jsx("span", { children: "Grant Screen Recording permission in System Settings -> Privacy." }), _jsxs("button", { type: "button", onClick: openPrivacy, className: "ms-1 inline-flex items-center gap-1 rounded border border-border px-1.5 py-0.5 text-[10px] text-muted-foreground hover:bg-accent/40 hover:text-foreground", children: [_jsx(IconLockOpen, { size: 10 }), "Open System Settings"] })] })] }));
428
428
  }
429
429
  export function VoiceTranscriptionIcon() {
430
430
  return _jsx(IconMicrophone, { size: 14 });
@@ -1 +1 @@
1
- {"version":3,"file":"VoiceTranscriptionSection.js","sourceRoot":"","sources":["../../../src/client/settings/VoiceTranscriptionSection.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * <VoiceTranscriptionSection /> — source + cleanup settings for voice input.\n *\n * Writes the selection to application_state under `voice-transcription-prefs`\n * so the composer's `useVoiceDictation` hook picks it up on next record. The\n * legacy `provider` field is still written alongside `transcriptionMode` so\n * older clients continue to normalize safely.\n *\n * Provider status comes from `/_agent-native/voice-providers/status`, which\n * mirrors the server transcription route's key/env resolution.\n */\n\nimport React, { useCallback, useEffect, useState } from \"react\";\nimport { agentNativePath } from \"../api-path.js\";\nimport {\n IconAlertCircle,\n IconCheck,\n IconChevronDown,\n IconChevronRight,\n IconExternalLink,\n IconLoader2,\n IconLockOpen,\n IconMicrophone,\n} from \"@tabler/icons-react\";\nimport {\n openBuilderConnectPopup,\n useBuilderStatus,\n} from \"./useBuilderStatus.js\";\n\ntype TranscriptionMode = \"mac-native\" | \"google-realtime\" | \"batch\";\n\ntype Provider =\n | \"auto\"\n | \"openai\"\n | \"builder-gemini\"\n | \"builder\"\n | \"browser\"\n | \"gemini\"\n | \"groq\";\n\ninterface Prefs {\n transcriptionMode?: TranscriptionMode;\n provider?: Provider;\n instructions?: string;\n}\n\ninterface SecretStatus {\n key: string;\n status: \"set\" | \"unset\" | \"invalid\";\n}\n\ninterface ProviderStatus {\n builder: boolean;\n gemini: boolean;\n openai: boolean;\n groq: boolean;\n googleRealtime?: boolean;\n browser: true;\n native?: true;\n}\n\nconst PREFS_URL = agentNativePath(\n \"/_agent-native/application-state/voice-transcription-prefs\",\n);\nconst CLEANUP_PREFS_URL = agentNativePath(\n \"/_agent-native/application-state/voice-cleanup-prefs\",\n);\nconst SECRETS_URL = agentNativePath(\"/_agent-native/secrets\");\nconst PROVIDER_STATUS_URL = agentNativePath(\n \"/_agent-native/voice-providers/status\",\n);\nconst DEFAULT_TRANSCRIPTION_MODE: TranscriptionMode = \"batch\";\nconst DEFAULT_BATCH_PROVIDER: Provider = \"auto\";\n\nfunction isProvider(value: unknown): value is Provider {\n return (\n value === \"auto\" ||\n value === \"openai\" ||\n value === \"builder-gemini\" ||\n value === \"builder\" ||\n value === \"browser\" ||\n value === \"gemini\" ||\n value === \"groq\"\n );\n}\n\nfunction isTranscriptionMode(value: unknown): value is TranscriptionMode {\n return (\n value === \"mac-native\" || value === \"google-realtime\" || value === \"batch\"\n );\n}\n\nfunction normalizeProvider(value: unknown): Provider | null {\n if (!isProvider(value)) return null;\n return value === \"builder\" ? \"builder-gemini\" : value;\n}\n\nfunction legacyModeFromProvider(provider: Provider | null): TranscriptionMode {\n if (provider === \"browser\") return \"mac-native\";\n return \"batch\";\n}\n\nfunction providerForMode(\n mode: TranscriptionMode,\n currentProvider: Provider | null,\n): Provider {\n if (mode === \"mac-native\") return \"browser\";\n if (mode === \"google-realtime\") return \"auto\";\n if (!currentProvider || currentProvider === \"browser\") {\n return DEFAULT_BATCH_PROVIDER;\n }\n return currentProvider;\n}\n\nfunction batchProvider(provider: Provider | null): Provider {\n if (!provider || provider === \"browser\") return DEFAULT_BATCH_PROVIDER;\n return provider;\n}\n\nexport function VoiceTranscriptionSection() {\n const [transcriptionMode, setTranscriptionMode] =\n useState<TranscriptionMode | null>(null);\n const [provider, setProvider] = useState<Provider>(DEFAULT_BATCH_PROVIDER);\n const [instructions, setInstructions] = useState(\"\");\n const [openAiConfigured, setOpenAiConfigured] = useState<boolean | null>(\n null,\n );\n const [geminiConfigured, setGeminiConfigured] = useState<boolean | null>(\n null,\n );\n const [groqConfigured, setGroqConfigured] = useState<boolean | null>(null);\n const [googleRealtimeConfigured, setGoogleRealtimeConfigured] = useState<\n boolean | null\n >(null);\n const [saving, setSaving] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n const [showAdvanced, setShowAdvanced] = useState(false);\n const [cleanupEnabled, setCleanupEnabled] = useState<boolean | null>(null);\n const { status: builderStatus } = useBuilderStatus();\n const builderRealtimeReady =\n !!builderStatus?.privateKeyConfigured &&\n !!builderStatus?.publicKeyConfigured;\n const googleRealtimeReady =\n !!googleRealtimeConfigured && builderRealtimeReady;\n\n // Read cleanup pref (default: true if Builder is connected).\n useEffect(() => {\n let cancelled = false;\n fetch(CLEANUP_PREFS_URL)\n .then((r) => (r.ok ? r.json() : null))\n .then(\n (\n body:\n | { enabled?: boolean }\n | { value?: { enabled?: boolean } }\n | null,\n ) => {\n if (cancelled) return;\n const stored =\n (body as { enabled?: boolean } | null)?.enabled ??\n (body as { value?: { enabled?: boolean } } | null)?.value?.enabled;\n if (typeof stored === \"boolean\") setCleanupEnabled(stored);\n else setCleanupEnabled(null); // resolve once builderStatus arrives\n },\n )\n .catch(() => !cancelled && setCleanupEnabled(null));\n return () => {\n cancelled = true;\n };\n }, []);\n\n useEffect(() => {\n if (cleanupEnabled !== null) return;\n if (builderStatus?.configured !== undefined) {\n setCleanupEnabled(!!builderStatus.configured);\n }\n }, [builderStatus?.configured, cleanupEnabled]);\n\n const toggleCleanup = async (next: boolean) => {\n const previous = cleanupEnabled;\n setCleanupEnabled(next);\n try {\n const res = await fetch(CLEANUP_PREFS_URL, {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ enabled: next }),\n });\n if (!res.ok) {\n throw new Error(`HTTP ${res.status}`);\n }\n } catch {\n setCleanupEnabled(previous);\n }\n };\n\n useEffect(() => {\n let cancelled = false;\n fetch(PREFS_URL)\n .then((r) => (r.ok ? r.json() : null))\n .then((body: Prefs | { value?: Prefs } | null) => {\n if (cancelled) return;\n const value =\n (body as { value?: Prefs } | null)?.value ?? (body as Prefs | null);\n const p = normalizeProvider(\n (body as Prefs | null)?.provider ??\n (body as { value?: Prefs } | null)?.value?.provider,\n );\n const storedMode = isTranscriptionMode(value?.transcriptionMode)\n ? value.transcriptionMode\n : null;\n const mode =\n storedMode ??\n (p ? legacyModeFromProvider(p) : DEFAULT_TRANSCRIPTION_MODE);\n const savedInstructions =\n (body as Prefs | null)?.instructions ??\n (body as { value?: Prefs } | null)?.value?.instructions;\n setTranscriptionMode(mode);\n setProvider(providerForMode(mode, p));\n if (typeof savedInstructions === \"string\") {\n setInstructions(savedInstructions);\n }\n })\n .catch(() => {\n if (!cancelled) {\n setTranscriptionMode(DEFAULT_TRANSCRIPTION_MODE);\n setProvider(DEFAULT_BATCH_PROVIDER);\n }\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n useEffect(() => {\n let cancelled = false;\n fetch(PROVIDER_STATUS_URL)\n .then((r) => (r.ok ? r.json() : null))\n .then((status: ProviderStatus | null) => {\n if (cancelled) return;\n if (status) {\n setOpenAiConfigured(status.openai);\n setGeminiConfigured(status.gemini);\n setGroqConfigured(status.groq);\n setGoogleRealtimeConfigured(!!status.googleRealtime);\n return;\n }\n return fetch(SECRETS_URL)\n .then((r) => (r.ok ? r.json() : []))\n .then((list: SecretStatus[]) => {\n if (cancelled) return;\n const find = (key: string) =>\n Array.isArray(list) ? list.find((s) => s.key === key) : null;\n setOpenAiConfigured(find(\"OPENAI_API_KEY\")?.status === \"set\");\n setGeminiConfigured(find(\"GEMINI_API_KEY\")?.status === \"set\");\n setGroqConfigured(find(\"GROQ_API_KEY\")?.status === \"set\");\n setGoogleRealtimeConfigured(\n find(\"GOOGLE_APPLICATION_CREDENTIALS\")?.status === \"set\",\n );\n });\n })\n .catch(() => {\n if (!cancelled) {\n setOpenAiConfigured(false);\n setGeminiConfigured(false);\n setGroqConfigured(false);\n setGoogleRealtimeConfigured(false);\n }\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n const persist = useCallback(\n async (\n nextMode: TranscriptionMode,\n nextProvider: Provider,\n nextInstructions: string,\n previous: {\n transcriptionMode: TranscriptionMode | null;\n provider: Provider;\n instructions: string;\n },\n ) => {\n setSaving(true);\n setSaveError(null);\n try {\n const res = await fetch(PREFS_URL, {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n transcriptionMode: nextMode,\n provider: nextProvider,\n instructions: nextInstructions.trim(),\n }),\n });\n if (!res.ok) {\n throw new Error(`HTTP ${res.status}`);\n }\n } catch (err) {\n // Revert the optimistic update so the UI matches server state.\n setTranscriptionMode(previous.transcriptionMode);\n setProvider(previous.provider);\n setInstructions(previous.instructions);\n setSaveError(\n `Couldn't save: ${(err as Error)?.message ?? \"network error\"}. Try again.`,\n );\n } finally {\n setSaving(false);\n }\n },\n [],\n );\n\n const focusKey = (key: string) => {\n if (typeof window === \"undefined\") return;\n window.location.hash = `#secrets:${key}`;\n };\n\n const chooseSource = (next: TranscriptionMode) => {\n if (next === transcriptionMode) return;\n if (next === \"google-realtime\" && !googleRealtimeReady) {\n setShowAdvanced(true);\n if (!googleRealtimeConfigured) {\n focusKey(\"GOOGLE_APPLICATION_CREDENTIALS\");\n } else if (!builderRealtimeReady) {\n openBuilderConnect();\n }\n return;\n }\n const previous = { transcriptionMode, provider, instructions };\n const nextProvider = providerForMode(next, provider);\n setTranscriptionMode(next);\n setProvider(nextProvider);\n void persist(next, nextProvider, instructions, previous);\n };\n\n const openBuilderConnect = () => {\n openBuilderConnectPopup({\n url: builderStatus?.cliAuthUrl ?? builderStatus?.connectUrl,\n source: \"voice_transcription_settings\",\n features: \"noopener,noreferrer,width=600,height=700\",\n });\n };\n\n const chooseBatchProvider = (next: Provider) => {\n const nextProvider = batchProvider(normalizeProvider(next));\n if (transcriptionMode === \"batch\" && nextProvider === provider) return;\n const previous = { transcriptionMode, provider, instructions };\n setTranscriptionMode(\"batch\");\n setProvider(nextProvider);\n void persist(\"batch\", nextProvider, instructions, previous);\n };\n\n const updateInstructions = (next: string) => {\n const previous = { transcriptionMode, provider, instructions };\n setInstructions(next);\n if (transcriptionMode) {\n void persist(transcriptionMode, provider, next, previous);\n }\n };\n\n if (transcriptionMode === null) {\n return (\n <div className=\"flex items-center gap-1.5 text-[10px] text-muted-foreground\">\n <IconLoader2 size={10} className=\"animate-spin\" />\n Loading…\n </div>\n );\n }\n\n return (\n <div className=\"space-y-2\">\n <div className=\"rounded-md border border-border bg-background p-2\">\n <div className=\"mb-2 flex items-start justify-between gap-3 px-0.5\">\n <div>\n <div className=\"text-[11px] font-medium text-foreground\">\n Live transcription\n </div>\n <p className=\"mt-0.5 text-[10px] text-muted-foreground\">\n Choose where real-time words come from. Batch still runs after\n recording stops.\n </p>\n </div>\n </div>\n <div className=\"space-y-2\">\n <ProviderOption\n id=\"mac-native\"\n selected={transcriptionMode === \"mac-native\"}\n onSelect={() => chooseSource(\"mac-native\")}\n title=\"Mac Native\"\n subtitle=\"Free and fast in the macOS Tauri app. Web clients use the existing browser-native path when available.\"\n rightSlot={\n <span className=\"text-[10px] text-muted-foreground\">\n Tauri default\n </span>\n }\n />\n <ProviderOption\n id=\"google-realtime\"\n selected={transcriptionMode === \"google-realtime\"}\n onSelect={() => chooseSource(\"google-realtime\")}\n disabled={!googleRealtimeReady}\n title=\"Google Realtime\"\n subtitle={\n googleRealtimeReady\n ? \"BYOK only for v1. Streams live partials and finals through Google Speech-to-Text.\"\n : googleRealtimeConfigured\n ? \"Google credentials are set. Connect Builder completely to mint the managed realtime session.\"\n : \"BYOK only for v1. Configure Google service account before selecting this source.\"\n }\n rightSlot={\n googleRealtimeReady ? (\n <span className=\"flex items-center gap-1 text-[10px] text-green-500\">\n <IconCheck size={10} />\n Ready\n </span>\n ) : googleRealtimeConfigured ? (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n openBuilderConnect();\n }}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:bg-accent/40 hover:text-foreground\"\n >\n Connect Builder.io\n <IconExternalLink size={10} />\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n setShowAdvanced(true);\n focusKey(\"GOOGLE_APPLICATION_CREDENTIALS\");\n }}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:bg-accent/40 hover:text-foreground\"\n >\n Configure\n <IconExternalLink size={10} />\n </button>\n )\n }\n />\n <ProviderOption\n id=\"batch\"\n selected={transcriptionMode === \"batch\"}\n onSelect={() => chooseSource(\"batch\")}\n title=\"Batch\"\n subtitle=\"Universal fallback. Sends audio after recording stops through Builder Gemini, Gemini, Groq, then OpenAI.\"\n />\n <SystemAudioStatus />\n </div>\n </div>\n\n <div className=\"flex items-start justify-between gap-3 rounded-md border border-border bg-accent/30 px-2.5 py-2\">\n <div className=\"min-w-0\">\n <div className=\"text-[11px] font-medium text-foreground\">\n AI cleanup\n </div>\n <p className=\"text-[10px] text-muted-foreground mt-0.5\">\n Polish punctuation, casing, filler words, titles, and summaries\n after capture. Builder Gemini is tried first; BYOK Gemini is the\n fallback.\n </p>\n </div>\n <div className=\"flex shrink-0 flex-col items-end gap-1\">\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={!!cleanupEnabled}\n onClick={() => toggleCleanup(!cleanupEnabled)}\n // Theme tokens; streaming agent owns layout.\n className={`relative inline-flex h-4 w-7 shrink-0 cursor-pointer items-center rounded-full transition-colors ${\n cleanupEnabled\n ? \"bg-primary\"\n : \"bg-muted-foreground/30 hover:bg-muted-foreground/50\"\n }`}\n >\n <span\n className={`inline-block h-3 w-3 transform rounded-full bg-background transition-transform ${\n cleanupEnabled ? \"translate-x-3.5\" : \"translate-x-0.5\"\n }`}\n />\n </button>\n {cleanupEnabled && (\n <span className=\"text-[10px] text-muted-foreground\">\n {builderStatus?.configured\n ? \"Builder ready\"\n : geminiConfigured\n ? \"Gemini key set\"\n : \"Needs key\"}\n </span>\n )}\n </div>\n </div>\n\n <div className=\"rounded-md border border-border bg-background\">\n <button\n type=\"button\"\n onClick={() => setShowAdvanced((v) => !v)}\n className=\"w-full flex items-center justify-between gap-2 px-2.5 py-2 cursor-pointer\"\n >\n <span className=\"text-[11px] font-medium text-foreground inline-flex items-center gap-1\">\n {showAdvanced ? (\n <IconChevronDown size={12} />\n ) : (\n <IconChevronRight size={12} />\n )}\n Add API keys\n </span>\n <span className=\"text-[10px] text-muted-foreground\">\n Google STT · Gemini · Groq · OpenAI\n </span>\n </button>\n\n {showAdvanced && (\n <div className=\"px-2 pb-2 space-y-2\">\n <ProviderOption\n id=\"google-service-account\"\n selected={transcriptionMode === \"google-realtime\"}\n onSelect={() => chooseSource(\"google-realtime\")}\n disabled={!googleRealtimeReady}\n title=\"Google Speech-to-Text service account\"\n subtitle={\n googleRealtimeConfigured\n ? \"Service-account JSON is set. Connect Builder to mint the managed realtime WebSocket session.\"\n : \"Service-account JSON for the dedicated realtime WebSocket to Google StreamingRecognize.\"\n }\n rightSlot={\n googleRealtimeConfigured ===\n null ? null : googleRealtimeReady ? (\n <span className=\"flex items-center gap-1 text-[10px] text-green-500\">\n <IconCheck size={10} />\n Ready\n </span>\n ) : googleRealtimeConfigured ? (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n openBuilderConnect();\n }}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40\"\n >\n Connect Builder.io\n <IconExternalLink size={10} />\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n focusKey(\"GOOGLE_APPLICATION_CREDENTIALS\");\n }}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40\"\n >\n Configure\n <IconExternalLink size={10} />\n </button>\n )\n }\n />\n\n <ProviderOption\n id=\"auto\"\n selected={transcriptionMode === \"batch\" && provider === \"auto\"}\n onSelect={() => chooseBatchProvider(\"auto\")}\n title=\"Automatic batch fallback\"\n subtitle=\"Keep the current Clips fallback chain: Builder Gemini, Gemini, Groq, then OpenAI.\"\n />\n\n <ProviderOption\n id=\"builder-gemini\"\n selected={\n transcriptionMode === \"batch\" && provider === \"builder-gemini\"\n }\n onSelect={() => chooseBatchProvider(\"builder-gemini\")}\n disabled={!builderStatus?.configured}\n title=\"Builder.io Connect\"\n subtitle={\n builderStatus?.configured\n ? \"Use Builder-hosted Gemini Flash-Lite for batch transcription and cleanup.\"\n : \"One-click connect for Gemini Flash-Lite cleanup and batch transcription. No Google key needed.\"\n }\n rightSlot={\n builderStatus?.configured ? (\n <span className=\"flex items-center gap-1 text-[10px] text-green-500\">\n <IconCheck size={10} />\n Connected\n </span>\n ) : (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n openBuilderConnect();\n }}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40\"\n >\n Connect Builder.io\n <IconExternalLink size={10} />\n </button>\n )\n }\n />\n\n <ProviderOption\n id=\"gemini\"\n selected={transcriptionMode === \"batch\" && provider === \"gemini\"}\n onSelect={() => chooseBatchProvider(\"gemini\")}\n title=\"Google Gemini\"\n subtitle=\"BYOK Gemini for AI cleanup and optional strict batch transcription.\"\n rightSlot={\n geminiConfigured === null ? null : geminiConfigured ? (\n <span className=\"flex items-center gap-1 text-[10px] text-green-500\">\n <IconCheck size={10} />\n Key set\n </span>\n ) : (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n focusKey(\"GEMINI_API_KEY\");\n }}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40\"\n >\n Add key\n <IconExternalLink size={10} />\n </button>\n )\n }\n />\n\n <ProviderOption\n id=\"openai\"\n selected={transcriptionMode === \"batch\" && provider === \"openai\"}\n onSelect={() => chooseBatchProvider(\"openai\")}\n title=\"OpenAI Whisper\"\n subtitle=\"Batch Whisper provider. Requires an OpenAI API key.\"\n rightSlot={\n openAiConfigured === null ? null : openAiConfigured ? (\n <span className=\"flex items-center gap-1 text-[10px] text-green-500\">\n <IconCheck size={10} />\n Key set\n </span>\n ) : (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n focusKey(\"OPENAI_API_KEY\");\n }}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40\"\n >\n Add key\n <IconExternalLink size={10} />\n </button>\n )\n }\n />\n\n <ProviderOption\n id=\"groq\"\n selected={transcriptionMode === \"batch\" && provider === \"groq\"}\n onSelect={() => chooseBatchProvider(\"groq\")}\n title=\"Groq Whisper\"\n subtitle=\"Fast Whisper batch provider. Requires a Groq API key.\"\n rightSlot={\n groqConfigured === null ? null : groqConfigured ? (\n <span className=\"flex items-center gap-1 text-[10px] text-green-500\">\n <IconCheck size={10} />\n Key set\n </span>\n ) : (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n focusKey(\"GROQ_API_KEY\");\n }}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40\"\n >\n Add key\n <IconExternalLink size={10} />\n </button>\n )\n }\n />\n </div>\n )}\n </div>\n\n {(cleanupEnabled || transcriptionMode === \"batch\") && (\n <div className=\"rounded-md border border-border bg-accent/20 px-2.5 py-2\">\n <label\n htmlFor=\"voice-transcription-instructions\"\n className=\"block text-[10px] font-medium text-foreground\"\n >\n Custom instructions\n </label>\n <textarea\n id=\"voice-transcription-instructions\"\n value={instructions}\n onChange={(event) => updateInstructions(event.target.value)}\n placeholder=\"Names, casing, punctuation, style, or terms to preserve.\"\n className=\"mt-1 min-h-16 w-full resize-y rounded border border-border bg-background px-2 py-1.5 text-[11px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-accent\"\n />\n <p className=\"mt-1 text-[10px] text-muted-foreground\">\n Included with batch transcription and AI cleanup.\n </p>\n </div>\n )}\n\n {saveError && !saving && (\n <p className=\"text-[10px] text-red-500\" role=\"alert\">\n {saveError}\n </p>\n )}\n </div>\n );\n}\n\ninterface ProviderOptionProps {\n id: string;\n selected: boolean;\n disabled?: boolean;\n onSelect: () => void;\n title: string;\n subtitle?: React.ReactNode;\n rightSlot?: React.ReactNode;\n}\n\nfunction ProviderOption({\n id: _id,\n selected,\n disabled,\n onSelect,\n title,\n subtitle,\n rightSlot,\n}: ProviderOptionProps) {\n const select = () => {\n if (!disabled) onSelect();\n };\n\n const onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (disabled) return;\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n onSelect();\n }\n };\n\n return (\n <div\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n onClick={select}\n onKeyDown={onKeyDown}\n aria-pressed={selected}\n aria-disabled={disabled || undefined}\n // Theme tokens; streaming agent owns layout.\n className={`w-full text-left rounded-md border px-2.5 py-2 flex items-start gap-2 ${\n selected\n ? \"border-primary bg-primary/10\"\n : \"border-border bg-accent/30 hover:bg-accent/50\"\n } ${disabled ? \"opacity-60 cursor-not-allowed\" : \"\"}`}\n >\n <span\n className={`mt-[2px] shrink-0 flex h-3.5 w-3.5 items-center justify-center rounded-full border ${\n selected\n ? \"border-primary bg-primary\"\n : \"border-muted-foreground/40 bg-background\"\n }`}\n >\n {selected && (\n <span className=\"h-1.5 w-1.5 rounded-full bg-primary-foreground\" />\n )}\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"text-[11px] font-medium text-foreground\">{title}</div>\n {rightSlot && <div className=\"shrink-0\">{rightSlot}</div>}\n </div>\n {subtitle && (\n <p className=\"text-[10px] text-muted-foreground mt-0.5\">{subtitle}</p>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Surfaces the desktop app's system-audio capture readiness inside the live\n * transcription box. Renders nothing in non-Tauri contexts (web users) so the\n * existing browser-only flow is unaffected. The Rust side\n * (`templates/clips/desktop/src-tauri/src/system_audio.rs`) returns either a\n * structured `VersionStatus` via `system_audio_version_status` (preferred,\n * no error-string parsing) or an unsupported-OS error from\n * `system_audio_request_permission`. We surface three states:\n *\n * - macOS 13+ + permission granted -> green check (\"System audio capture available\")\n * - macOS < 13 -> red dot (\"...requires macOS 13 or later\")\n * - permission denied / pending -> amber + \"Open System Settings\" affordance\n */\ntype SystemAudioState =\n | { kind: \"loading\" }\n | { kind: \"available\" }\n | { kind: \"unsupported\"; reason: string }\n | { kind: \"denied\" };\n\ninterface VersionStatusPayload {\n supported: boolean;\n os_version: string;\n reason?: string;\n}\n\n// Tauri v2 exposes `window.__TAURI_INTERNALS__.invoke` as the runtime entry\n// point that `@tauri-apps/api/core` itself wraps. Calling it directly avoids\n// pulling `@tauri-apps/api` into the web bundle's import graph — a dynamic\n// `import(\"@tauri-apps/api/core\")` survives Vite's prebundle as a literal\n// specifier and trips `vite:import-analysis` with a \"Failed to resolve\" error\n// in fresh CLI installs that don't have the desktop dep installed.\ntype TauriInvoke = (cmd: string, args?: unknown) => Promise<unknown>;\nfunction getTauriInvoke(): TauriInvoke | null {\n if (typeof window === \"undefined\") return null;\n const internals = (\n window as unknown as { __TAURI_INTERNALS__?: { invoke?: TauriInvoke } }\n ).__TAURI_INTERNALS__;\n return internals?.invoke ?? null;\n}\n\nfunction SystemAudioStatus() {\n const [state, setState] = useState<SystemAudioState | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n const invoke = getTauriInvoke();\n if (!invoke) return; // Web users: render nothing.\n setState({ kind: \"loading\" });\n void (async () => {\n try {\n const status = (await invoke(\"system_audio_version_status\")) as\n | VersionStatusPayload\n | undefined;\n if (cancelled) return;\n if (status && !status.supported) {\n setState({\n kind: \"unsupported\",\n reason:\n status.reason ??\n `ScreenCaptureKit is unavailable on ${status.os_version}.`,\n });\n return;\n }\n // Supported — now probe permission. This may prompt; calling it\n // here matches the original on-mount semantics requested in the\n // settings flow.\n try {\n const granted = (await invoke(\n \"system_audio_request_permission\",\n )) as boolean;\n if (cancelled) return;\n setState(granted ? { kind: \"available\" } : { kind: \"denied\" });\n } catch (err) {\n if (cancelled) return;\n const msg = String(err ?? \"\");\n if (/macOS\\s*1[0-2]|requires macOS 13/i.test(msg)) {\n setState({ kind: \"unsupported\", reason: msg });\n } else {\n setState({ kind: \"denied\" });\n }\n }\n } catch {\n // Older desktop builds may not have the new command yet —\n // fall back to the permission probe.\n if (cancelled) return;\n try {\n const granted = (await invoke(\n \"system_audio_request_permission\",\n )) as boolean;\n if (cancelled) return;\n setState(granted ? { kind: \"available\" } : { kind: \"denied\" });\n } catch (err) {\n if (cancelled) return;\n const msg = String(err ?? \"\");\n if (/macOS|ScreenCaptureKit/i.test(msg)) {\n setState({ kind: \"unsupported\", reason: msg });\n } else {\n setState({ kind: \"denied\" });\n }\n }\n }\n })();\n return () => {\n cancelled = true;\n };\n }, []);\n\n const openPrivacy = useCallback(() => {\n const invoke = getTauriInvoke();\n if (!invoke) return;\n void invoke(\"system_audio_open_privacy_settings\").catch(() => {\n // Older desktop builds without this command — no-op.\n });\n }, []);\n\n if (!state || state.kind === \"loading\") return null;\n\n if (state.kind === \"available\") {\n return (\n <div className=\"flex items-center gap-1.5 px-0.5 pt-1 text-[10px] text-muted-foreground\">\n <IconCheck size={11} className=\"text-green-500\" />\n <span>System audio capture available.</span>\n </div>\n );\n }\n\n if (state.kind === \"unsupported\") {\n return (\n <div className=\"flex items-center gap-1.5 px-0.5 pt-1 text-[10px] text-muted-foreground\">\n <span\n className=\"inline-block h-1.5 w-1.5 shrink-0 rounded-full bg-red-500\"\n aria-hidden\n />\n <span>\n System audio requires macOS 13 or later — meetings will use mic-only.\n </span>\n </div>\n );\n }\n\n // denied\n return (\n <div className=\"flex items-start gap-1.5 px-0.5 pt-1 text-[10px] text-muted-foreground\">\n <IconAlertCircle size={11} className=\"mt-[1px] shrink-0 text-amber-500\" />\n <div className=\"flex-1\">\n <span>\n Grant Screen Recording permission in System Settings -&gt; Privacy.\n </span>\n <button\n type=\"button\"\n onClick={openPrivacy}\n className=\"ml-1 inline-flex items-center gap-1 rounded border border-border px-1.5 py-0.5 text-[10px] text-muted-foreground hover:bg-accent/40 hover:text-foreground\"\n >\n <IconLockOpen size={10} />\n Open System Settings\n </button>\n </div>\n </div>\n );\n}\n\nexport function VoiceTranscriptionIcon() {\n return <IconMicrophone size={14} />;\n}\n"]}
1
+ {"version":3,"file":"VoiceTranscriptionSection.js","sourceRoot":"","sources":["../../../src/client/settings/VoiceTranscriptionSection.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * <VoiceTranscriptionSection /> — source + cleanup settings for voice input.\n *\n * Writes the selection to application_state under `voice-transcription-prefs`\n * so the composer's `useVoiceDictation` hook picks it up on next record. The\n * legacy `provider` field is still written alongside `transcriptionMode` so\n * older clients continue to normalize safely.\n *\n * Provider status comes from `/_agent-native/voice-providers/status`, which\n * mirrors the server transcription route's key/env resolution.\n */\n\nimport React, { useCallback, useEffect, useState } from \"react\";\nimport { agentNativePath } from \"../api-path.js\";\nimport {\n IconAlertCircle,\n IconCheck,\n IconChevronDown,\n IconChevronRight,\n IconExternalLink,\n IconLoader2,\n IconLockOpen,\n IconMicrophone,\n} from \"@tabler/icons-react\";\nimport {\n openBuilderConnectPopup,\n useBuilderStatus,\n} from \"./useBuilderStatus.js\";\n\ntype TranscriptionMode = \"mac-native\" | \"google-realtime\" | \"batch\";\n\ntype Provider =\n | \"auto\"\n | \"openai\"\n | \"builder-gemini\"\n | \"builder\"\n | \"browser\"\n | \"gemini\"\n | \"groq\";\n\ninterface Prefs {\n transcriptionMode?: TranscriptionMode;\n provider?: Provider;\n instructions?: string;\n}\n\ninterface SecretStatus {\n key: string;\n status: \"set\" | \"unset\" | \"invalid\";\n}\n\ninterface ProviderStatus {\n builder: boolean;\n gemini: boolean;\n openai: boolean;\n groq: boolean;\n googleRealtime?: boolean;\n browser: true;\n native?: true;\n}\n\nconst PREFS_URL = agentNativePath(\n \"/_agent-native/application-state/voice-transcription-prefs\",\n);\nconst CLEANUP_PREFS_URL = agentNativePath(\n \"/_agent-native/application-state/voice-cleanup-prefs\",\n);\nconst SECRETS_URL = agentNativePath(\"/_agent-native/secrets\");\nconst PROVIDER_STATUS_URL = agentNativePath(\n \"/_agent-native/voice-providers/status\",\n);\nconst DEFAULT_TRANSCRIPTION_MODE: TranscriptionMode = \"batch\";\nconst DEFAULT_BATCH_PROVIDER: Provider = \"auto\";\n\nfunction isProvider(value: unknown): value is Provider {\n return (\n value === \"auto\" ||\n value === \"openai\" ||\n value === \"builder-gemini\" ||\n value === \"builder\" ||\n value === \"browser\" ||\n value === \"gemini\" ||\n value === \"groq\"\n );\n}\n\nfunction isTranscriptionMode(value: unknown): value is TranscriptionMode {\n return (\n value === \"mac-native\" || value === \"google-realtime\" || value === \"batch\"\n );\n}\n\nfunction normalizeProvider(value: unknown): Provider | null {\n if (!isProvider(value)) return null;\n return value === \"builder\" ? \"builder-gemini\" : value;\n}\n\nfunction legacyModeFromProvider(provider: Provider | null): TranscriptionMode {\n if (provider === \"browser\") return \"mac-native\";\n return \"batch\";\n}\n\nfunction providerForMode(\n mode: TranscriptionMode,\n currentProvider: Provider | null,\n): Provider {\n if (mode === \"mac-native\") return \"browser\";\n if (mode === \"google-realtime\") return \"auto\";\n if (!currentProvider || currentProvider === \"browser\") {\n return DEFAULT_BATCH_PROVIDER;\n }\n return currentProvider;\n}\n\nfunction batchProvider(provider: Provider | null): Provider {\n if (!provider || provider === \"browser\") return DEFAULT_BATCH_PROVIDER;\n return provider;\n}\n\nexport function VoiceTranscriptionSection() {\n const [transcriptionMode, setTranscriptionMode] =\n useState<TranscriptionMode | null>(null);\n const [provider, setProvider] = useState<Provider>(DEFAULT_BATCH_PROVIDER);\n const [instructions, setInstructions] = useState(\"\");\n const [openAiConfigured, setOpenAiConfigured] = useState<boolean | null>(\n null,\n );\n const [geminiConfigured, setGeminiConfigured] = useState<boolean | null>(\n null,\n );\n const [groqConfigured, setGroqConfigured] = useState<boolean | null>(null);\n const [googleRealtimeConfigured, setGoogleRealtimeConfigured] = useState<\n boolean | null\n >(null);\n const [saving, setSaving] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n const [showAdvanced, setShowAdvanced] = useState(false);\n const [cleanupEnabled, setCleanupEnabled] = useState<boolean | null>(null);\n const { status: builderStatus } = useBuilderStatus();\n const builderRealtimeReady =\n !!builderStatus?.privateKeyConfigured &&\n !!builderStatus?.publicKeyConfigured;\n const googleRealtimeReady =\n !!googleRealtimeConfigured && builderRealtimeReady;\n\n // Read cleanup pref (default: true if Builder is connected).\n useEffect(() => {\n let cancelled = false;\n fetch(CLEANUP_PREFS_URL)\n .then((r) => (r.ok ? r.json() : null))\n .then(\n (\n body:\n | { enabled?: boolean }\n | { value?: { enabled?: boolean } }\n | null,\n ) => {\n if (cancelled) return;\n const stored =\n (body as { enabled?: boolean } | null)?.enabled ??\n (body as { value?: { enabled?: boolean } } | null)?.value?.enabled;\n if (typeof stored === \"boolean\") setCleanupEnabled(stored);\n else setCleanupEnabled(null); // resolve once builderStatus arrives\n },\n )\n .catch(() => !cancelled && setCleanupEnabled(null));\n return () => {\n cancelled = true;\n };\n }, []);\n\n useEffect(() => {\n if (cleanupEnabled !== null) return;\n if (builderStatus?.configured !== undefined) {\n setCleanupEnabled(!!builderStatus.configured);\n }\n }, [builderStatus?.configured, cleanupEnabled]);\n\n const toggleCleanup = async (next: boolean) => {\n const previous = cleanupEnabled;\n setCleanupEnabled(next);\n try {\n const res = await fetch(CLEANUP_PREFS_URL, {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ enabled: next }),\n });\n if (!res.ok) {\n throw new Error(`HTTP ${res.status}`);\n }\n } catch {\n setCleanupEnabled(previous);\n }\n };\n\n useEffect(() => {\n let cancelled = false;\n fetch(PREFS_URL)\n .then((r) => (r.ok ? r.json() : null))\n .then((body: Prefs | { value?: Prefs } | null) => {\n if (cancelled) return;\n const value =\n (body as { value?: Prefs } | null)?.value ?? (body as Prefs | null);\n const p = normalizeProvider(\n (body as Prefs | null)?.provider ??\n (body as { value?: Prefs } | null)?.value?.provider,\n );\n const storedMode = isTranscriptionMode(value?.transcriptionMode)\n ? value.transcriptionMode\n : null;\n const mode =\n storedMode ??\n (p ? legacyModeFromProvider(p) : DEFAULT_TRANSCRIPTION_MODE);\n const savedInstructions =\n (body as Prefs | null)?.instructions ??\n (body as { value?: Prefs } | null)?.value?.instructions;\n setTranscriptionMode(mode);\n setProvider(providerForMode(mode, p));\n if (typeof savedInstructions === \"string\") {\n setInstructions(savedInstructions);\n }\n })\n .catch(() => {\n if (!cancelled) {\n setTranscriptionMode(DEFAULT_TRANSCRIPTION_MODE);\n setProvider(DEFAULT_BATCH_PROVIDER);\n }\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n useEffect(() => {\n let cancelled = false;\n fetch(PROVIDER_STATUS_URL)\n .then((r) => (r.ok ? r.json() : null))\n .then((status: ProviderStatus | null) => {\n if (cancelled) return;\n if (status) {\n setOpenAiConfigured(status.openai);\n setGeminiConfigured(status.gemini);\n setGroqConfigured(status.groq);\n setGoogleRealtimeConfigured(!!status.googleRealtime);\n return;\n }\n return fetch(SECRETS_URL)\n .then((r) => (r.ok ? r.json() : []))\n .then((list: SecretStatus[]) => {\n if (cancelled) return;\n const find = (key: string) =>\n Array.isArray(list) ? list.find((s) => s.key === key) : null;\n setOpenAiConfigured(find(\"OPENAI_API_KEY\")?.status === \"set\");\n setGeminiConfigured(find(\"GEMINI_API_KEY\")?.status === \"set\");\n setGroqConfigured(find(\"GROQ_API_KEY\")?.status === \"set\");\n setGoogleRealtimeConfigured(\n find(\"GOOGLE_APPLICATION_CREDENTIALS\")?.status === \"set\",\n );\n });\n })\n .catch(() => {\n if (!cancelled) {\n setOpenAiConfigured(false);\n setGeminiConfigured(false);\n setGroqConfigured(false);\n setGoogleRealtimeConfigured(false);\n }\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n const persist = useCallback(\n async (\n nextMode: TranscriptionMode,\n nextProvider: Provider,\n nextInstructions: string,\n previous: {\n transcriptionMode: TranscriptionMode | null;\n provider: Provider;\n instructions: string;\n },\n ) => {\n setSaving(true);\n setSaveError(null);\n try {\n const res = await fetch(PREFS_URL, {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n transcriptionMode: nextMode,\n provider: nextProvider,\n instructions: nextInstructions.trim(),\n }),\n });\n if (!res.ok) {\n throw new Error(`HTTP ${res.status}`);\n }\n } catch (err) {\n // Revert the optimistic update so the UI matches server state.\n setTranscriptionMode(previous.transcriptionMode);\n setProvider(previous.provider);\n setInstructions(previous.instructions);\n setSaveError(\n `Couldn't save: ${(err as Error)?.message ?? \"network error\"}. Try again.`,\n );\n } finally {\n setSaving(false);\n }\n },\n [],\n );\n\n const focusKey = (key: string) => {\n if (typeof window === \"undefined\") return;\n window.location.hash = `#secrets:${key}`;\n };\n\n const chooseSource = (next: TranscriptionMode) => {\n if (next === transcriptionMode) return;\n if (next === \"google-realtime\" && !googleRealtimeReady) {\n setShowAdvanced(true);\n if (!googleRealtimeConfigured) {\n focusKey(\"GOOGLE_APPLICATION_CREDENTIALS\");\n } else if (!builderRealtimeReady) {\n openBuilderConnect();\n }\n return;\n }\n const previous = { transcriptionMode, provider, instructions };\n const nextProvider = providerForMode(next, provider);\n setTranscriptionMode(next);\n setProvider(nextProvider);\n void persist(next, nextProvider, instructions, previous);\n };\n\n const openBuilderConnect = () => {\n openBuilderConnectPopup({\n url: builderStatus?.cliAuthUrl ?? builderStatus?.connectUrl,\n source: \"voice_transcription_settings\",\n features: \"noopener,noreferrer,width=600,height=700\",\n });\n };\n\n const chooseBatchProvider = (next: Provider) => {\n const nextProvider = batchProvider(normalizeProvider(next));\n if (transcriptionMode === \"batch\" && nextProvider === provider) return;\n const previous = { transcriptionMode, provider, instructions };\n setTranscriptionMode(\"batch\");\n setProvider(nextProvider);\n void persist(\"batch\", nextProvider, instructions, previous);\n };\n\n const updateInstructions = (next: string) => {\n const previous = { transcriptionMode, provider, instructions };\n setInstructions(next);\n if (transcriptionMode) {\n void persist(transcriptionMode, provider, next, previous);\n }\n };\n\n if (transcriptionMode === null) {\n return (\n <div className=\"flex items-center gap-1.5 text-[10px] text-muted-foreground\">\n <IconLoader2 size={10} className=\"animate-spin\" />\n Loading…\n </div>\n );\n }\n\n return (\n <div className=\"space-y-2\">\n <div className=\"rounded-md border border-border bg-background p-2\">\n <div className=\"mb-2 flex items-start justify-between gap-3 px-0.5\">\n <div>\n <div className=\"text-[11px] font-medium text-foreground\">\n Live transcription\n </div>\n <p className=\"mt-0.5 text-[10px] text-muted-foreground\">\n Choose where real-time words come from. Batch still runs after\n recording stops.\n </p>\n </div>\n </div>\n <div className=\"space-y-2\">\n <ProviderOption\n id=\"mac-native\"\n selected={transcriptionMode === \"mac-native\"}\n onSelect={() => chooseSource(\"mac-native\")}\n title=\"Mac Native\"\n subtitle=\"Free and fast in the macOS Tauri app. Web clients use the existing browser-native path when available.\"\n rightSlot={\n <span className=\"text-[10px] text-muted-foreground\">\n Tauri default\n </span>\n }\n />\n <ProviderOption\n id=\"google-realtime\"\n selected={transcriptionMode === \"google-realtime\"}\n onSelect={() => chooseSource(\"google-realtime\")}\n disabled={!googleRealtimeReady}\n title=\"Google Realtime\"\n subtitle={\n googleRealtimeReady\n ? \"BYOK only for v1. Streams live partials and finals through Google Speech-to-Text.\"\n : googleRealtimeConfigured\n ? \"Google credentials are set. Connect Builder completely to mint the managed realtime session.\"\n : \"BYOK only for v1. Configure Google service account before selecting this source.\"\n }\n rightSlot={\n googleRealtimeReady ? (\n <span className=\"flex items-center gap-1 text-[10px] text-green-500\">\n <IconCheck size={10} />\n Ready\n </span>\n ) : googleRealtimeConfigured ? (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n openBuilderConnect();\n }}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:bg-accent/40 hover:text-foreground\"\n >\n Connect Builder.io\n <IconExternalLink size={10} />\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n setShowAdvanced(true);\n focusKey(\"GOOGLE_APPLICATION_CREDENTIALS\");\n }}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:bg-accent/40 hover:text-foreground\"\n >\n Configure\n <IconExternalLink size={10} />\n </button>\n )\n }\n />\n <ProviderOption\n id=\"batch\"\n selected={transcriptionMode === \"batch\"}\n onSelect={() => chooseSource(\"batch\")}\n title=\"Batch\"\n subtitle=\"Universal fallback. Sends audio after recording stops through Builder Gemini, Gemini, Groq, then OpenAI.\"\n />\n <SystemAudioStatus />\n </div>\n </div>\n\n <div className=\"flex items-start justify-between gap-3 rounded-md border border-border bg-accent/30 px-2.5 py-2\">\n <div className=\"min-w-0\">\n <div className=\"text-[11px] font-medium text-foreground\">\n AI cleanup\n </div>\n <p className=\"text-[10px] text-muted-foreground mt-0.5\">\n Polish punctuation, casing, filler words, titles, and summaries\n after capture. Builder Gemini is tried first; BYOK Gemini is the\n fallback.\n </p>\n </div>\n <div className=\"flex shrink-0 flex-col items-end gap-1\">\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={!!cleanupEnabled}\n onClick={() => toggleCleanup(!cleanupEnabled)}\n // Theme tokens; streaming agent owns layout.\n className={`relative inline-flex h-4 w-7 shrink-0 cursor-pointer items-center rounded-full transition-colors ${\n cleanupEnabled\n ? \"bg-primary\"\n : \"bg-muted-foreground/30 hover:bg-muted-foreground/50\"\n }`}\n >\n <span\n className={`inline-block h-3 w-3 transform rounded-full bg-background transition-transform ${\n cleanupEnabled ? \"translate-x-3.5\" : \"translate-x-0.5\"\n }`}\n />\n </button>\n {cleanupEnabled && (\n <span className=\"text-[10px] text-muted-foreground\">\n {builderStatus?.configured\n ? \"Builder ready\"\n : geminiConfigured\n ? \"Gemini key set\"\n : \"Needs key\"}\n </span>\n )}\n </div>\n </div>\n\n <div className=\"rounded-md border border-border bg-background\">\n <button\n type=\"button\"\n onClick={() => setShowAdvanced((v) => !v)}\n className=\"w-full flex items-center justify-between gap-2 px-2.5 py-2 cursor-pointer\"\n >\n <span className=\"text-[11px] font-medium text-foreground inline-flex items-center gap-1\">\n {showAdvanced ? (\n <IconChevronDown size={12} />\n ) : (\n <IconChevronRight size={12} className=\"rtl:-scale-x-100\" />\n )}\n Add API keys\n </span>\n <span className=\"text-[10px] text-muted-foreground\">\n Google STT · Gemini · Groq · OpenAI\n </span>\n </button>\n\n {showAdvanced && (\n <div className=\"px-2 pb-2 space-y-2\">\n <ProviderOption\n id=\"google-service-account\"\n selected={transcriptionMode === \"google-realtime\"}\n onSelect={() => chooseSource(\"google-realtime\")}\n disabled={!googleRealtimeReady}\n title=\"Google Speech-to-Text service account\"\n subtitle={\n googleRealtimeConfigured\n ? \"Service-account JSON is set. Connect Builder to mint the managed realtime WebSocket session.\"\n : \"Service-account JSON for the dedicated realtime WebSocket to Google StreamingRecognize.\"\n }\n rightSlot={\n googleRealtimeConfigured ===\n null ? null : googleRealtimeReady ? (\n <span className=\"flex items-center gap-1 text-[10px] text-green-500\">\n <IconCheck size={10} />\n Ready\n </span>\n ) : googleRealtimeConfigured ? (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n openBuilderConnect();\n }}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40\"\n >\n Connect Builder.io\n <IconExternalLink size={10} />\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n focusKey(\"GOOGLE_APPLICATION_CREDENTIALS\");\n }}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40\"\n >\n Configure\n <IconExternalLink size={10} />\n </button>\n )\n }\n />\n\n <ProviderOption\n id=\"auto\"\n selected={transcriptionMode === \"batch\" && provider === \"auto\"}\n onSelect={() => chooseBatchProvider(\"auto\")}\n title=\"Automatic batch fallback\"\n subtitle=\"Keep the current Clips fallback chain: Builder Gemini, Gemini, Groq, then OpenAI.\"\n />\n\n <ProviderOption\n id=\"builder-gemini\"\n selected={\n transcriptionMode === \"batch\" && provider === \"builder-gemini\"\n }\n onSelect={() => chooseBatchProvider(\"builder-gemini\")}\n disabled={!builderStatus?.configured}\n title=\"Builder.io Connect\"\n subtitle={\n builderStatus?.configured\n ? \"Use Builder-hosted Gemini Flash-Lite for batch transcription and cleanup.\"\n : \"One-click connect for Gemini Flash-Lite cleanup and batch transcription. No Google key needed.\"\n }\n rightSlot={\n builderStatus?.configured ? (\n <span className=\"flex items-center gap-1 text-[10px] text-green-500\">\n <IconCheck size={10} />\n Connected\n </span>\n ) : (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n openBuilderConnect();\n }}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40\"\n >\n Connect Builder.io\n <IconExternalLink size={10} />\n </button>\n )\n }\n />\n\n <ProviderOption\n id=\"gemini\"\n selected={transcriptionMode === \"batch\" && provider === \"gemini\"}\n onSelect={() => chooseBatchProvider(\"gemini\")}\n title=\"Google Gemini\"\n subtitle=\"BYOK Gemini for AI cleanup and optional strict batch transcription.\"\n rightSlot={\n geminiConfigured === null ? null : geminiConfigured ? (\n <span className=\"flex items-center gap-1 text-[10px] text-green-500\">\n <IconCheck size={10} />\n Key set\n </span>\n ) : (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n focusKey(\"GEMINI_API_KEY\");\n }}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40\"\n >\n Add key\n <IconExternalLink size={10} />\n </button>\n )\n }\n />\n\n <ProviderOption\n id=\"openai\"\n selected={transcriptionMode === \"batch\" && provider === \"openai\"}\n onSelect={() => chooseBatchProvider(\"openai\")}\n title=\"OpenAI Whisper\"\n subtitle=\"Batch Whisper provider. Requires an OpenAI API key.\"\n rightSlot={\n openAiConfigured === null ? null : openAiConfigured ? (\n <span className=\"flex items-center gap-1 text-[10px] text-green-500\">\n <IconCheck size={10} />\n Key set\n </span>\n ) : (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n focusKey(\"OPENAI_API_KEY\");\n }}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40\"\n >\n Add key\n <IconExternalLink size={10} />\n </button>\n )\n }\n />\n\n <ProviderOption\n id=\"groq\"\n selected={transcriptionMode === \"batch\" && provider === \"groq\"}\n onSelect={() => chooseBatchProvider(\"groq\")}\n title=\"Groq Whisper\"\n subtitle=\"Fast Whisper batch provider. Requires a Groq API key.\"\n rightSlot={\n groqConfigured === null ? null : groqConfigured ? (\n <span className=\"flex items-center gap-1 text-[10px] text-green-500\">\n <IconCheck size={10} />\n Key set\n </span>\n ) : (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n focusKey(\"GROQ_API_KEY\");\n }}\n className=\"inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40\"\n >\n Add key\n <IconExternalLink size={10} />\n </button>\n )\n }\n />\n </div>\n )}\n </div>\n\n {(cleanupEnabled || transcriptionMode === \"batch\") && (\n <div className=\"rounded-md border border-border bg-accent/20 px-2.5 py-2\">\n <label\n htmlFor=\"voice-transcription-instructions\"\n className=\"block text-[10px] font-medium text-foreground\"\n >\n Custom instructions\n </label>\n <textarea\n id=\"voice-transcription-instructions\"\n value={instructions}\n onChange={(event) => updateInstructions(event.target.value)}\n placeholder=\"Names, casing, punctuation, style, or terms to preserve.\"\n className=\"mt-1 min-h-16 w-full resize-y rounded border border-border bg-background px-2 py-1.5 text-[11px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-accent\"\n />\n <p className=\"mt-1 text-[10px] text-muted-foreground\">\n Included with batch transcription and AI cleanup.\n </p>\n </div>\n )}\n\n {saveError && !saving && (\n <p className=\"text-[10px] text-red-500\" role=\"alert\">\n {saveError}\n </p>\n )}\n </div>\n );\n}\n\ninterface ProviderOptionProps {\n id: string;\n selected: boolean;\n disabled?: boolean;\n onSelect: () => void;\n title: string;\n subtitle?: React.ReactNode;\n rightSlot?: React.ReactNode;\n}\n\nfunction ProviderOption({\n id: _id,\n selected,\n disabled,\n onSelect,\n title,\n subtitle,\n rightSlot,\n}: ProviderOptionProps) {\n const select = () => {\n if (!disabled) onSelect();\n };\n\n const onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (disabled) return;\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n onSelect();\n }\n };\n\n return (\n <div\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n onClick={select}\n onKeyDown={onKeyDown}\n aria-pressed={selected}\n aria-disabled={disabled || undefined}\n // Theme tokens; streaming agent owns layout.\n className={`w-full text-start rounded-md border px-2.5 py-2 flex items-start gap-2 ${\n selected\n ? \"border-primary bg-primary/10\"\n : \"border-border bg-accent/30 hover:bg-accent/50\"\n } ${disabled ? \"opacity-60 cursor-not-allowed\" : \"\"}`}\n >\n <span\n className={`mt-[2px] shrink-0 flex h-3.5 w-3.5 items-center justify-center rounded-full border ${\n selected\n ? \"border-primary bg-primary\"\n : \"border-muted-foreground/40 bg-background\"\n }`}\n >\n {selected && (\n <span className=\"h-1.5 w-1.5 rounded-full bg-primary-foreground\" />\n )}\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"text-[11px] font-medium text-foreground\">{title}</div>\n {rightSlot && <div className=\"shrink-0\">{rightSlot}</div>}\n </div>\n {subtitle && (\n <p className=\"text-[10px] text-muted-foreground mt-0.5\">{subtitle}</p>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Surfaces the desktop app's system-audio capture readiness inside the live\n * transcription box. Renders nothing in non-Tauri contexts (web users) so the\n * existing browser-only flow is unaffected. The Rust side\n * (`templates/clips/desktop/src-tauri/src/system_audio.rs`) returns either a\n * structured `VersionStatus` via `system_audio_version_status` (preferred,\n * no error-string parsing) or an unsupported-OS error from\n * `system_audio_request_permission`. We surface three states:\n *\n * - macOS 13+ + permission granted -> green check (\"System audio capture available\")\n * - macOS < 13 -> red dot (\"...requires macOS 13 or later\")\n * - permission denied / pending -> amber + \"Open System Settings\" affordance\n */\ntype SystemAudioState =\n | { kind: \"loading\" }\n | { kind: \"available\" }\n | { kind: \"unsupported\"; reason: string }\n | { kind: \"denied\" };\n\ninterface VersionStatusPayload {\n supported: boolean;\n os_version: string;\n reason?: string;\n}\n\n// Tauri v2 exposes `window.__TAURI_INTERNALS__.invoke` as the runtime entry\n// point that `@tauri-apps/api/core` itself wraps. Calling it directly avoids\n// pulling `@tauri-apps/api` into the web bundle's import graph — a dynamic\n// `import(\"@tauri-apps/api/core\")` survives Vite's prebundle as a literal\n// specifier and trips `vite:import-analysis` with a \"Failed to resolve\" error\n// in fresh CLI installs that don't have the desktop dep installed.\ntype TauriInvoke = (cmd: string, args?: unknown) => Promise<unknown>;\nfunction getTauriInvoke(): TauriInvoke | null {\n if (typeof window === \"undefined\") return null;\n const internals = (\n window as unknown as { __TAURI_INTERNALS__?: { invoke?: TauriInvoke } }\n ).__TAURI_INTERNALS__;\n return internals?.invoke ?? null;\n}\n\nfunction SystemAudioStatus() {\n const [state, setState] = useState<SystemAudioState | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n const invoke = getTauriInvoke();\n if (!invoke) return; // Web users: render nothing.\n setState({ kind: \"loading\" });\n void (async () => {\n try {\n const status = (await invoke(\"system_audio_version_status\")) as\n | VersionStatusPayload\n | undefined;\n if (cancelled) return;\n if (status && !status.supported) {\n setState({\n kind: \"unsupported\",\n reason:\n status.reason ??\n `ScreenCaptureKit is unavailable on ${status.os_version}.`,\n });\n return;\n }\n // Supported — now probe permission. This may prompt; calling it\n // here matches the original on-mount semantics requested in the\n // settings flow.\n try {\n const granted = (await invoke(\n \"system_audio_request_permission\",\n )) as boolean;\n if (cancelled) return;\n setState(granted ? { kind: \"available\" } : { kind: \"denied\" });\n } catch (err) {\n if (cancelled) return;\n const msg = String(err ?? \"\");\n if (/macOS\\s*1[0-2]|requires macOS 13/i.test(msg)) {\n setState({ kind: \"unsupported\", reason: msg });\n } else {\n setState({ kind: \"denied\" });\n }\n }\n } catch {\n // Older desktop builds may not have the new command yet —\n // fall back to the permission probe.\n if (cancelled) return;\n try {\n const granted = (await invoke(\n \"system_audio_request_permission\",\n )) as boolean;\n if (cancelled) return;\n setState(granted ? { kind: \"available\" } : { kind: \"denied\" });\n } catch (err) {\n if (cancelled) return;\n const msg = String(err ?? \"\");\n if (/macOS|ScreenCaptureKit/i.test(msg)) {\n setState({ kind: \"unsupported\", reason: msg });\n } else {\n setState({ kind: \"denied\" });\n }\n }\n }\n })();\n return () => {\n cancelled = true;\n };\n }, []);\n\n const openPrivacy = useCallback(() => {\n const invoke = getTauriInvoke();\n if (!invoke) return;\n void invoke(\"system_audio_open_privacy_settings\").catch(() => {\n // Older desktop builds without this command — no-op.\n });\n }, []);\n\n if (!state || state.kind === \"loading\") return null;\n\n if (state.kind === \"available\") {\n return (\n <div className=\"flex items-center gap-1.5 px-0.5 pt-1 text-[10px] text-muted-foreground\">\n <IconCheck size={11} className=\"text-green-500\" />\n <span>System audio capture available.</span>\n </div>\n );\n }\n\n if (state.kind === \"unsupported\") {\n return (\n <div className=\"flex items-center gap-1.5 px-0.5 pt-1 text-[10px] text-muted-foreground\">\n <span\n className=\"inline-block h-1.5 w-1.5 shrink-0 rounded-full bg-red-500\"\n aria-hidden\n />\n <span>\n System audio requires macOS 13 or later — meetings will use mic-only.\n </span>\n </div>\n );\n }\n\n // denied\n return (\n <div className=\"flex items-start gap-1.5 px-0.5 pt-1 text-[10px] text-muted-foreground\">\n <IconAlertCircle size={11} className=\"mt-[1px] shrink-0 text-amber-500\" />\n <div className=\"flex-1\">\n <span>\n Grant Screen Recording permission in System Settings -&gt; Privacy.\n </span>\n <button\n type=\"button\"\n onClick={openPrivacy}\n className=\"ms-1 inline-flex items-center gap-1 rounded border border-border px-1.5 py-0.5 text-[10px] text-muted-foreground hover:bg-accent/40 hover:text-foreground\"\n >\n <IconLockOpen size={10} />\n Open System Settings\n </button>\n </div>\n </div>\n );\n}\n\nexport function VoiceTranscriptionIcon() {\n return <IconMicrophone size={14} />;\n}\n"]}
@@ -505,7 +505,7 @@ function SharePanel(props) {
505
505
  : displayName(s.principalId, knownMembers) }), canManage ? (_jsx(RoleSelect, { value: s.role, onChange: (r) => handleChangeRole(s, r), disabled: inFlight.has(keyOf(s)), plain: true })) : (_jsx("span", { className: "text-xs text-muted-foreground", children: cap(s.role) })), canManage ? (_jsx("button", { type: "button", "aria-label": "Remove", onClick: () => handleRemove(s), disabled: inFlight.has(keyOf(s)), className: BUTTON_GHOST_ICON, children: _jsx(IconTrash, { size: 14 }) })) : null] }, keyOf(s)))), !shares.length && !data?.ownerEmail ? (_jsx("li", { className: "px-1 py-1.5 text-sm text-muted-foreground", children: "No one has access yet." })) : null] }), _jsx("div", { className: "mb-2 text-sm font-semibold", children: generalAccessLabel }), _jsxs("div", { className: "mb-4 flex items-center gap-3", children: [_jsx("span", { "aria-hidden": true, className: "inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground", children: _jsx(meta.Icon, { size: 16, strokeWidth: 1.75 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx(VisibilitySelect, { value: visibility, onChange: handleVisibility, disabled: !canManage, visibilityCopy: props.visibilityCopy, allowPublic: policy.allowPublic }), _jsxs("div", { className: "mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-muted-foreground", children: [_jsx("span", { children: meta.description }), visibility === "org" && props.hideInSearchControl ? (_jsx(AdvancedAccessPopover, { control: props.hideInSearchControl, canManage: canManage, onToggle: handleHideInSearch })) : null] })] })] }), props.accessNote ? (_jsx("div", { className: "mb-4 rounded-md border border-border bg-muted/35 p-3 text-xs text-muted-foreground", children: props.accessNote })) : null, showShareLinks && shareUrlPlacement === "bottom" ? shareLinks : null, _jsx("div", { className: "mt-2 flex justify-end", children: _jsx("button", { type: "button", onClick: handleDone, className: BUTTON_PRIMARY_SM, children: "Done" }) })] }));
506
506
  }
507
507
  function AdvancedAccessPopover({ control, canManage, onToggle, }) {
508
- return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", disabled: !canManage, className: "inline-flex items-center gap-1 rounded-sm px-1 py-0.5 text-xs font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50", children: ["Advanced", _jsx(IconChevronDown, { size: 12, strokeWidth: 1.8 })] }) }), _jsx(PopoverContent, { align: "start", sideOffset: 6, onOpenAutoFocus: (event) => event.preventDefault(), className: cn("z-[2300] w-72 p-3 shadow-lg", SHARE_POPOVER_SURFACE), children: _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: "Advanced access" }), _jsx("div", { className: "mt-1 text-xs leading-5 text-muted-foreground", children: "Control how organization access appears in search." })] }), _jsxs("button", { type: "button", role: "switch", "aria-checked": control.checked, disabled: !canManage || control.pending, onClick: onToggle, className: cn("flex w-full items-start gap-3 rounded-md border border-border/70 bg-background px-3 py-2.5 text-left transition-colors hover:bg-accent/45 disabled:cursor-not-allowed disabled:opacity-60", control.checked && "border-border bg-accent/35 text-foreground"), children: [_jsx("span", { "aria-hidden": true, className: cn("relative mt-0.5 inline-flex h-5 w-9 shrink-0 items-center rounded-full border border-border bg-muted-foreground/25 transition-colors", control.checked && "border-primary/70 bg-primary"), children: _jsx("span", { className: cn("ml-0.5 size-4 rounded-full bg-background shadow-sm transition-transform", control.checked && "translate-x-4") }) }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsxs("span", { className: "flex items-center gap-1.5 text-sm font-medium text-foreground", children: [_jsx(IconSearchOff, { size: 14, strokeWidth: 1.8 }), control.label ?? "Hide in search"] }), _jsx("span", { className: "mt-0.5 block text-xs leading-5 text-muted-foreground", children: control.description ??
508
+ return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", disabled: !canManage, className: "inline-flex items-center gap-1 rounded-sm px-1 py-0.5 text-xs font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50", children: ["Advanced", _jsx(IconChevronDown, { size: 12, strokeWidth: 1.8 })] }) }), _jsx(PopoverContent, { align: "start", sideOffset: 6, onOpenAutoFocus: (event) => event.preventDefault(), className: cn("z-[2300] w-72 p-3 shadow-lg", SHARE_POPOVER_SURFACE), children: _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: "Advanced access" }), _jsx("div", { className: "mt-1 text-xs leading-5 text-muted-foreground", children: "Control how organization access appears in search." })] }), _jsxs("button", { type: "button", role: "switch", "aria-checked": control.checked, disabled: !canManage || control.pending, onClick: onToggle, className: cn("flex w-full items-start gap-3 rounded-md border border-border/70 bg-background px-3 py-2.5 text-start transition-colors hover:bg-accent/45 disabled:cursor-not-allowed disabled:opacity-60", control.checked && "border-border bg-accent/35 text-foreground"), children: [_jsx("span", { "aria-hidden": true, className: cn("relative mt-0.5 inline-flex h-5 w-9 shrink-0 items-center rounded-full border border-border bg-muted-foreground/25 transition-colors", control.checked && "border-primary/70 bg-primary"), children: _jsx("span", { className: cn("ml-0.5 size-4 rounded-full bg-background shadow-sm transition-transform", control.checked && "translate-x-4") }) }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsxs("span", { className: "flex items-center gap-1.5 text-sm font-medium text-foreground", children: [_jsx(IconSearchOff, { size: 14, strokeWidth: 1.8 }), control.label ?? "Hide in search"] }), _jsx("span", { className: "mt-0.5 block text-xs leading-5 text-muted-foreground", children: control.description ??
509
509
  "People with the link can still open this." })] })] })] }) })] }));
510
510
  }
511
511
  function MemberAutocomplete({ value, open, onOpenChange, onValueChange, onSelectMember, onSubmit, placeholder, suggestions, search, }) {
@@ -587,7 +587,7 @@ function MemberAutocomplete({ value, open, onOpenChange, onValueChange, onSelect
587
587
  search.loadMore();
588
588
  }
589
589
  };
590
- return (_jsxs(Popover, { open: open, onOpenChange: onOpenChange, children: [_jsx(PopoverAnchor, { asChild: true, children: _jsxs("div", { className: "relative flex-1 min-w-0", children: [_jsx(IconSearch, { "aria-hidden": true, size: 15, strokeWidth: 1.8, className: "pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-muted-foreground" }), _jsx("input", { ref: inputRef, type: "email", role: "combobox", "aria-autocomplete": "list", "aria-expanded": open, "aria-controls": open ? listboxId : undefined, "aria-activedescendant": activeIndex >= 0 ? optionId(listboxId, activeIndex) : undefined, placeholder: placeholder, value: value, onChange: (event) => {
590
+ return (_jsxs(Popover, { open: open, onOpenChange: onOpenChange, children: [_jsx(PopoverAnchor, { asChild: true, children: _jsxs("div", { className: "relative flex-1 min-w-0", children: [_jsx(IconSearch, { "aria-hidden": true, size: 15, strokeWidth: 1.8, className: "pointer-events-none absolute start-2.5 top-1/2 -translate-y-1/2 text-muted-foreground" }), _jsx("input", { ref: inputRef, type: "email", role: "combobox", "aria-autocomplete": "list", "aria-expanded": open, "aria-controls": open ? listboxId : undefined, "aria-activedescendant": activeIndex >= 0 ? optionId(listboxId, activeIndex) : undefined, placeholder: placeholder, value: value, onChange: (event) => {
591
591
  onValueChange(event.target.value);
592
592
  onOpenChange(true);
593
593
  }, onFocus: () => onOpenChange(true), onBlur: () => {
@@ -596,7 +596,7 @@ function MemberAutocomplete({ value, open, onOpenChange, onValueChange, onSelect
596
596
  onOpenChange(false);
597
597
  }
598
598
  }, 0);
599
- }, onKeyDown: handleKeyDown, autoComplete: "off", className: "h-9 w-full min-w-0 rounded-md border border-input bg-background pl-8 pr-8 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background" }), search.isLoading ? (_jsx(IconLoader2, { "aria-hidden": true, size: 15, strokeWidth: 1.8, className: "pointer-events-none absolute right-2.5 top-1/2 -translate-y-1/2 animate-spin text-muted-foreground" })) : null] }) }), _jsx(PopoverContent, { align: "start", sideOffset: 4, onOpenAutoFocus: (event) => event.preventDefault(), className: cn("z-[2200] w-[var(--radix-popper-anchor-width)] min-w-[18rem] rounded-md p-1 shadow-lg", SHARE_POPOVER_SURFACE), children: _jsxs("div", { id: listboxId, role: "listbox", className: "max-h-56 overflow-y-auto overflow-x-hidden", onScroll: handleScroll, children: [suggestions.map((member, index) => {
599
+ }, onKeyDown: handleKeyDown, autoComplete: "off", className: "h-9 w-full min-w-0 rounded-md border border-input bg-background ps-8 pe-8 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background" }), search.isLoading ? (_jsx(IconLoader2, { "aria-hidden": true, size: 15, strokeWidth: 1.8, className: "pointer-events-none absolute end-2.5 top-1/2 -translate-y-1/2 animate-spin text-muted-foreground" })) : null] }) }), _jsx(PopoverContent, { align: "start", sideOffset: 4, onOpenAutoFocus: (event) => event.preventDefault(), className: cn("z-[2200] w-[var(--radix-popper-anchor-width)] min-w-[18rem] rounded-md p-1 shadow-lg", SHARE_POPOVER_SURFACE), children: _jsxs("div", { id: listboxId, role: "listbox", className: "max-h-56 overflow-y-auto overflow-x-hidden", onScroll: handleScroll, children: [suggestions.map((member, index) => {
600
600
  const active = index === activeIndex;
601
601
  return (_jsxs("div", { id: optionId(listboxId, index), role: "option", "aria-selected": active, onMouseDown: (event) => event.preventDefault(), onMouseEnter: () => setActiveIndex(index), onClick: () => chooseMember(member), className: cn("flex cursor-pointer select-none flex-col rounded-sm px-3 py-2 text-sm outline-none", active
602
602
  ? "bg-accent text-accent-foreground"
@@ -632,9 +632,9 @@ function CopyLinkField({ value, label = "Share link", description, }) {
632
632
  // Radix Select wrappers styled like shadcn Select (no native <select> anywhere)
633
633
  // ---------------------------------------------------------------------------
634
634
  const selectContentClass = "z-[2100] min-w-[12rem] overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0";
635
- const selectItemClass = "relative flex w-full cursor-pointer select-none items-start gap-2 rounded-sm py-2 pl-8 pr-3 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50";
635
+ const selectItemClass = "relative flex w-full cursor-pointer select-none items-start gap-2 rounded-sm py-2 ps-8 pe-3 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50";
636
636
  function SelectItems({ items }) {
637
- return (_jsx(_Fragment, { children: items.map((it) => (_jsxs(Select.Item, { value: it.value, className: selectItemClass, children: [_jsx("span", { className: "absolute left-2 top-2 flex h-4 w-4 items-center justify-center", children: _jsx(Select.ItemIndicator, { children: _jsx(IconCheck, { size: 14 }) }) }), _jsxs("span", { className: "flex flex-col", children: [_jsx(Select.ItemText, { children: it.label }), it.description ? (_jsx("span", { className: "text-xs text-muted-foreground", children: it.description })) : null] })] }, it.value))) }));
637
+ return (_jsx(_Fragment, { children: items.map((it) => (_jsxs(Select.Item, { value: it.value, className: selectItemClass, children: [_jsx("span", { className: "absolute start-2 top-2 flex h-4 w-4 items-center justify-center", children: _jsx(Select.ItemIndicator, { children: _jsx(IconCheck, { size: 14 }) }) }), _jsxs("span", { className: "flex flex-col", children: [_jsx(Select.ItemText, { children: it.label }), it.description ? (_jsx("span", { className: "text-xs text-muted-foreground", children: it.description })) : null] })] }, it.value))) }));
638
638
  }
639
639
  function RoleSelect(props) {
640
640
  const current = ROLE_OPTIONS.find((o) => o.value === props.value) ?? ROLE_OPTIONS[0];
@@ -646,7 +646,7 @@ function VisibilitySelect(props) {
646
646
  const allowPublic = props.allowPublic !== false;
647
647
  const current = visibilityMeta(props.value, props.visibilityCopy);
648
648
  const options = Object.keys(VIS_META).filter((k) => allowPublic || k !== "public");
649
- return (_jsxs(Select.Root, { value: props.value, onValueChange: (v) => props.onChange(v), disabled: props.disabled, children: [_jsxs(Select.Trigger, { className: cn(BUTTON_BASE, "h-7 px-1 -ml-1 bg-transparent text-foreground hover:bg-accent hover:text-accent-foreground"), "aria-label": "General access", children: [_jsx(Select.Value, { children: current.label }), _jsx(Select.Icon, { children: _jsx(IconChevronDown, { size: 14 }) })] }), _jsx(Select.Portal, { children: _jsx(Select.Content, { className: selectContentClass, position: "popper", sideOffset: 4, children: _jsx(Select.Viewport, { children: _jsx(SelectItems, { items: options.map((k) => ({
649
+ return (_jsxs(Select.Root, { value: props.value, onValueChange: (v) => props.onChange(v), disabled: props.disabled, children: [_jsxs(Select.Trigger, { className: cn(BUTTON_BASE, "h-7 px-1 -ms-1 bg-transparent text-foreground hover:bg-accent hover:text-accent-foreground"), "aria-label": "General access", children: [_jsx(Select.Value, { children: current.label }), _jsx(Select.Icon, { children: _jsx(IconChevronDown, { size: 14 }) })] }), _jsx(Select.Portal, { children: _jsx(Select.Content, { className: selectContentClass, position: "popper", sideOffset: 4, children: _jsx(Select.Viewport, { children: _jsx(SelectItems, { items: options.map((k) => ({
650
650
  value: k,
651
651
  label: visibilityMeta(k, props.visibilityCopy).label,
652
652
  description: visibilityMeta(k, props.visibilityCopy)