@elizaos/agent 2.0.0-alpha.385 → 2.0.0-alpha.392

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 (374) hide show
  1. package/apps/app-companion/src/components/companion/CompanionAppView.d.ts.map +1 -1
  2. package/apps/app-companion/src/components/companion/CompanionAppView.js +6 -4
  3. package/apps/app-companion/src/components/companion/CompanionView.d.ts.map +1 -1
  4. package/apps/app-companion/src/components/companion/CompanionView.js +6 -4
  5. package/apps/app-knowledge/src/routes.d.ts +1 -1
  6. package/apps/app-knowledge/src/routes.d.ts.map +1 -1
  7. package/apps/app-knowledge/src/routes.js +1 -1
  8. package/apps/app-lifeops/src/api/client-lifeops.js +6 -0
  9. package/apps/app-lifeops/src/components/AppBlockerSettingsCard.d.ts +3 -0
  10. package/apps/app-lifeops/src/components/AppBlockerSettingsCard.d.ts.map +1 -0
  11. package/apps/app-lifeops/src/components/AppBlockerSettingsCard.js +189 -0
  12. package/apps/app-lifeops/src/components/BrowserBridgeSetupPanel.d.ts +2 -0
  13. package/apps/app-lifeops/src/components/BrowserBridgeSetupPanel.d.ts.map +1 -0
  14. package/apps/app-lifeops/src/components/BrowserBridgeSetupPanel.js +1065 -0
  15. package/apps/app-lifeops/src/components/BrowserBridgeStatusChip.d.ts +7 -0
  16. package/apps/app-lifeops/src/components/BrowserBridgeStatusChip.d.ts.map +1 -0
  17. package/apps/app-lifeops/src/components/BrowserBridgeStatusChip.js +71 -0
  18. package/apps/app-lifeops/src/components/DataSourcesStrip.d.ts +14 -0
  19. package/apps/app-lifeops/src/components/DataSourcesStrip.d.ts.map +1 -0
  20. package/apps/app-lifeops/src/components/DataSourcesStrip.js +36 -0
  21. package/apps/app-lifeops/src/components/EventEditorDrawer.d.ts +23 -0
  22. package/apps/app-lifeops/src/components/EventEditorDrawer.d.ts.map +1 -0
  23. package/apps/app-lifeops/src/components/EventEditorDrawer.js +514 -0
  24. package/apps/app-lifeops/src/components/LifeOpsActivitySignalsEffect.d.ts +2 -0
  25. package/apps/app-lifeops/src/components/LifeOpsActivitySignalsEffect.d.ts.map +1 -0
  26. package/apps/app-lifeops/src/components/LifeOpsActivitySignalsEffect.js +10 -0
  27. package/apps/app-lifeops/src/components/LifeOpsCalendarSection.d.ts +15 -0
  28. package/apps/app-lifeops/src/components/LifeOpsCalendarSection.d.ts.map +1 -0
  29. package/apps/app-lifeops/src/components/LifeOpsCalendarSection.js +515 -0
  30. package/apps/app-lifeops/src/components/LifeOpsChatAdapter.d.ts +34 -0
  31. package/apps/app-lifeops/src/components/LifeOpsChatAdapter.d.ts.map +1 -0
  32. package/apps/app-lifeops/src/components/LifeOpsChatAdapter.js +175 -0
  33. package/apps/app-lifeops/src/components/LifeOpsFeatureTogglesSection.d.ts +2 -0
  34. package/apps/app-lifeops/src/components/LifeOpsFeatureTogglesSection.d.ts.map +1 -0
  35. package/apps/app-lifeops/src/components/LifeOpsFeatureTogglesSection.js +99 -0
  36. package/apps/app-lifeops/src/components/LifeOpsHabitVisuals.d.ts +37 -0
  37. package/apps/app-lifeops/src/components/LifeOpsHabitVisuals.d.ts.map +1 -0
  38. package/apps/app-lifeops/src/components/LifeOpsHabitVisuals.js +88 -0
  39. package/apps/app-lifeops/src/components/LifeOpsInboxSection.d.ts +13 -0
  40. package/apps/app-lifeops/src/components/LifeOpsInboxSection.d.ts.map +1 -0
  41. package/apps/app-lifeops/src/components/LifeOpsInboxSection.js +490 -0
  42. package/apps/app-lifeops/src/components/LifeOpsLinkBankButton.d.ts +12 -0
  43. package/apps/app-lifeops/src/components/LifeOpsLinkBankButton.d.ts.map +1 -0
  44. package/apps/app-lifeops/src/components/LifeOpsLinkBankButton.js +92 -0
  45. package/apps/app-lifeops/src/components/LifeOpsLinkPaypalButton.d.ts +12 -0
  46. package/apps/app-lifeops/src/components/LifeOpsLinkPaypalButton.d.ts.map +1 -0
  47. package/apps/app-lifeops/src/components/LifeOpsLinkPaypalButton.js +160 -0
  48. package/apps/app-lifeops/src/components/LifeOpsMoneySection.d.ts +3 -0
  49. package/apps/app-lifeops/src/components/LifeOpsMoneySection.d.ts.map +1 -0
  50. package/apps/app-lifeops/src/components/LifeOpsMoneySection.js +373 -0
  51. package/apps/app-lifeops/src/components/LifeOpsNavRail.d.ts +9 -0
  52. package/apps/app-lifeops/src/components/LifeOpsNavRail.d.ts.map +1 -0
  53. package/apps/app-lifeops/src/components/LifeOpsNavRail.js +93 -0
  54. package/apps/app-lifeops/src/components/LifeOpsOperationalPanels.d.ts +4 -0
  55. package/apps/app-lifeops/src/components/LifeOpsOperationalPanels.d.ts.map +1 -0
  56. package/apps/app-lifeops/src/components/LifeOpsOperationalPanels.js +274 -0
  57. package/apps/app-lifeops/src/components/LifeOpsOverviewSection.d.ts +7 -0
  58. package/apps/app-lifeops/src/components/LifeOpsOverviewSection.d.ts.map +1 -0
  59. package/apps/app-lifeops/src/components/LifeOpsOverviewSection.js +657 -0
  60. package/apps/app-lifeops/src/components/LifeOpsPageSections.d.ts +42 -0
  61. package/apps/app-lifeops/src/components/LifeOpsPageSections.d.ts.map +1 -0
  62. package/apps/app-lifeops/src/components/LifeOpsPageSections.js +166 -0
  63. package/apps/app-lifeops/src/components/LifeOpsPageView.d.ts +2 -0
  64. package/apps/app-lifeops/src/components/LifeOpsPageView.d.ts.map +1 -0
  65. package/apps/app-lifeops/src/components/LifeOpsPageView.js +566 -0
  66. package/apps/app-lifeops/src/components/LifeOpsRemindersSection.d.ts +2 -0
  67. package/apps/app-lifeops/src/components/LifeOpsRemindersSection.d.ts.map +1 -0
  68. package/apps/app-lifeops/src/components/LifeOpsRemindersSection.js +749 -0
  69. package/apps/app-lifeops/src/components/LifeOpsResizableSidebar.d.ts +27 -0
  70. package/apps/app-lifeops/src/components/LifeOpsResizableSidebar.d.ts.map +1 -0
  71. package/apps/app-lifeops/src/components/LifeOpsResizableSidebar.js +106 -0
  72. package/apps/app-lifeops/src/components/LifeOpsScreenTimeSection.d.ts +2 -0
  73. package/apps/app-lifeops/src/components/LifeOpsScreenTimeSection.d.ts.map +1 -0
  74. package/apps/app-lifeops/src/components/LifeOpsScreenTimeSection.js +373 -0
  75. package/apps/app-lifeops/src/components/LifeOpsSectionContent.d.ts +10 -0
  76. package/apps/app-lifeops/src/components/LifeOpsSectionContent.d.ts.map +1 -0
  77. package/apps/app-lifeops/src/components/LifeOpsSectionContent.js +30 -0
  78. package/apps/app-lifeops/src/components/LifeOpsSelectionContext.d.ts +21 -0
  79. package/apps/app-lifeops/src/components/LifeOpsSelectionContext.d.ts.map +1 -0
  80. package/apps/app-lifeops/src/components/LifeOpsSelectionContext.js +30 -0
  81. package/apps/app-lifeops/src/components/LifeOpsSettingsSection.d.ts +20 -0
  82. package/apps/app-lifeops/src/components/LifeOpsSettingsSection.d.ts.map +1 -0
  83. package/apps/app-lifeops/src/components/LifeOpsSettingsSection.js +597 -0
  84. package/apps/app-lifeops/src/components/LifeOpsSetupGate.d.ts +13 -0
  85. package/apps/app-lifeops/src/components/LifeOpsSetupGate.d.ts.map +1 -0
  86. package/apps/app-lifeops/src/components/LifeOpsSetupGate.js +134 -0
  87. package/apps/app-lifeops/src/components/LifeOpsSleepSection.d.ts +10 -0
  88. package/apps/app-lifeops/src/components/LifeOpsSleepSection.d.ts.map +1 -0
  89. package/apps/app-lifeops/src/components/LifeOpsSleepSection.js +425 -0
  90. package/apps/app-lifeops/src/components/LifeOpsWorkspaceShell.d.ts +11 -0
  91. package/apps/app-lifeops/src/components/LifeOpsWorkspaceShell.d.ts.map +1 -0
  92. package/apps/app-lifeops/src/components/LifeOpsWorkspaceShell.js +49 -0
  93. package/apps/app-lifeops/src/components/LifeOpsWorkspaceView.d.ts +2 -0
  94. package/apps/app-lifeops/src/components/LifeOpsWorkspaceView.d.ts.map +1 -0
  95. package/apps/app-lifeops/src/components/LifeOpsWorkspaceView.js +1041 -0
  96. package/apps/app-lifeops/src/components/MessagingConnectorCards.d.ts +7 -0
  97. package/apps/app-lifeops/src/components/MessagingConnectorCards.d.ts.map +1 -0
  98. package/apps/app-lifeops/src/components/MessagingConnectorCards.js +643 -0
  99. package/apps/app-lifeops/src/components/MissingSourceCard.d.ts +9 -0
  100. package/apps/app-lifeops/src/components/MissingSourceCard.d.ts.map +1 -0
  101. package/apps/app-lifeops/src/components/MissingSourceCard.js +5 -0
  102. package/apps/app-lifeops/src/components/MobileSignalsSetupCard.d.ts +2 -0
  103. package/apps/app-lifeops/src/components/MobileSignalsSetupCard.d.ts.map +1 -0
  104. package/apps/app-lifeops/src/components/MobileSignalsSetupCard.js +163 -0
  105. package/apps/app-lifeops/src/components/SleepInspectionPanel.d.ts +8 -0
  106. package/apps/app-lifeops/src/components/SleepInspectionPanel.d.ts.map +1 -0
  107. package/apps/app-lifeops/src/components/SleepInspectionPanel.js +59 -0
  108. package/apps/app-lifeops/src/components/WebsiteBlockerSettingsCard.d.ts +3 -0
  109. package/apps/app-lifeops/src/components/WebsiteBlockerSettingsCard.d.ts.map +1 -0
  110. package/apps/app-lifeops/src/components/WebsiteBlockerSettingsCard.js +75 -0
  111. package/apps/app-lifeops/src/components/WhatsAppQrOverlay.d.ts +8 -0
  112. package/apps/app-lifeops/src/components/WhatsAppQrOverlay.d.ts.map +1 -0
  113. package/apps/app-lifeops/src/components/WhatsAppQrOverlay.js +48 -0
  114. package/apps/app-lifeops/src/components/lifeops-labels.d.ts +2 -0
  115. package/apps/app-lifeops/src/components/lifeops-labels.d.ts.map +1 -0
  116. package/apps/app-lifeops/src/components/lifeops-labels.js +5 -0
  117. package/apps/app-lifeops/src/events/index.d.ts +34 -0
  118. package/apps/app-lifeops/src/events/index.d.ts.map +1 -0
  119. package/apps/app-lifeops/src/events/index.js +23 -0
  120. package/apps/app-lifeops/src/hooks/useCalendarWeek.d.ts +28 -0
  121. package/apps/app-lifeops/src/hooks/useCalendarWeek.d.ts.map +1 -0
  122. package/apps/app-lifeops/src/hooks/useCalendarWeek.js +93 -0
  123. package/apps/app-lifeops/src/hooks/useDiscordConnector.d.ts +14 -0
  124. package/apps/app-lifeops/src/hooks/useDiscordConnector.d.ts.map +1 -0
  125. package/apps/app-lifeops/src/hooks/useDiscordConnector.js +126 -0
  126. package/apps/app-lifeops/src/hooks/useGoogleLifeOpsConnector.d.ts +29 -0
  127. package/apps/app-lifeops/src/hooks/useGoogleLifeOpsConnector.d.ts.map +1 -0
  128. package/apps/app-lifeops/src/hooks/useGoogleLifeOpsConnector.js +481 -0
  129. package/apps/app-lifeops/src/hooks/useIMessageConnector.d.ts +10 -0
  130. package/apps/app-lifeops/src/hooks/useIMessageConnector.d.ts.map +1 -0
  131. package/apps/app-lifeops/src/hooks/useIMessageConnector.js +50 -0
  132. package/apps/app-lifeops/src/hooks/useInbox.d.ts +34 -0
  133. package/apps/app-lifeops/src/hooks/useInbox.d.ts.map +1 -0
  134. package/apps/app-lifeops/src/hooks/useInbox.js +98 -0
  135. package/apps/app-lifeops/src/hooks/useLifeOpsActivitySignals.d.ts +2 -0
  136. package/apps/app-lifeops/src/hooks/useLifeOpsActivitySignals.d.ts.map +1 -0
  137. package/apps/app-lifeops/src/hooks/useLifeOpsActivitySignals.js +383 -0
  138. package/apps/app-lifeops/src/hooks/useLifeOpsAppState.d.ts +9 -0
  139. package/apps/app-lifeops/src/hooks/useLifeOpsAppState.d.ts.map +1 -0
  140. package/apps/app-lifeops/src/hooks/useLifeOpsAppState.js +83 -0
  141. package/apps/app-lifeops/src/hooks/useLifeOpsCapabilitiesStatus.d.ts +8 -0
  142. package/apps/app-lifeops/src/hooks/useLifeOpsCapabilitiesStatus.d.ts.map +1 -0
  143. package/apps/app-lifeops/src/hooks/useLifeOpsCapabilitiesStatus.js +60 -0
  144. package/apps/app-lifeops/src/hooks/useLifeOpsScheduleInspection.d.ts +18 -0
  145. package/apps/app-lifeops/src/hooks/useLifeOpsScheduleInspection.d.ts.map +1 -0
  146. package/apps/app-lifeops/src/hooks/useLifeOpsScheduleInspection.js +66 -0
  147. package/apps/app-lifeops/src/hooks/useLifeOpsScheduleState.d.ts +14 -0
  148. package/apps/app-lifeops/src/hooks/useLifeOpsScheduleState.d.ts.map +1 -0
  149. package/apps/app-lifeops/src/hooks/useLifeOpsScheduleState.js +79 -0
  150. package/apps/app-lifeops/src/hooks/useLifeOpsSection.d.ts +18 -0
  151. package/apps/app-lifeops/src/hooks/useLifeOpsSection.d.ts.map +1 -0
  152. package/apps/app-lifeops/src/hooks/useLifeOpsSection.js +78 -0
  153. package/apps/app-lifeops/src/hooks/useLifeOpsXConnector.d.ts +14 -0
  154. package/apps/app-lifeops/src/hooks/useLifeOpsXConnector.d.ts.map +1 -0
  155. package/apps/app-lifeops/src/hooks/useLifeOpsXConnector.js +160 -0
  156. package/apps/app-lifeops/src/hooks/useSignalConnector.d.ts +16 -0
  157. package/apps/app-lifeops/src/hooks/useSignalConnector.d.ts.map +1 -0
  158. package/apps/app-lifeops/src/hooks/useSignalConnector.js +198 -0
  159. package/apps/app-lifeops/src/hooks/useTelegramConnector.d.ts +21 -0
  160. package/apps/app-lifeops/src/hooks/useTelegramConnector.d.ts.map +1 -0
  161. package/apps/app-lifeops/src/hooks/useTelegramConnector.js +177 -0
  162. package/apps/app-lifeops/src/hooks/useWhatsAppConnector.d.ts +8 -0
  163. package/apps/app-lifeops/src/hooks/useWhatsAppConnector.d.ts.map +1 -0
  164. package/apps/app-lifeops/src/hooks/useWhatsAppConnector.js +58 -0
  165. package/apps/app-lifeops/src/hooks/useWhatsAppPairing.d.ts +12 -0
  166. package/apps/app-lifeops/src/hooks/useWhatsAppPairing.d.ts.map +1 -0
  167. package/apps/app-lifeops/src/hooks/useWhatsAppPairing.js +152 -0
  168. package/apps/app-lifeops/src/lifeops/discord-browser-scraper.js +1 -1
  169. package/apps/app-lifeops/src/lifeops/google-gmail.d.ts.map +1 -1
  170. package/apps/app-lifeops/src/lifeops/google-gmail.js +74 -26
  171. package/apps/app-lifeops/src/lifeops/google-managed-client.d.ts.map +1 -1
  172. package/apps/app-lifeops/src/lifeops/google-managed-client.js +4 -5
  173. package/apps/app-lifeops/src/lifeops/google-oauth.d.ts.map +1 -1
  174. package/apps/app-lifeops/src/lifeops/google-oauth.js +2 -2
  175. package/apps/app-lifeops/src/lifeops/owner-profile.d.ts.map +1 -1
  176. package/apps/app-lifeops/src/lifeops/owner-profile.js +1 -1
  177. package/apps/app-lifeops/src/lifeops/paypal-managed-client.d.ts.map +1 -1
  178. package/apps/app-lifeops/src/lifeops/paypal-managed-client.js +4 -5
  179. package/apps/app-lifeops/src/lifeops/plaid-managed-client.d.ts.map +1 -1
  180. package/apps/app-lifeops/src/lifeops/plaid-managed-client.js +4 -5
  181. package/apps/app-lifeops/src/lifeops/schedule-sync-client.js +2 -2
  182. package/apps/app-lifeops/src/lifeops/service-constants.d.ts +1 -0
  183. package/apps/app-lifeops/src/lifeops/service-constants.d.ts.map +1 -1
  184. package/apps/app-lifeops/src/lifeops/service-constants.js +1 -0
  185. package/apps/app-lifeops/src/lifeops/service-mixin-core.d.ts +1 -1
  186. package/apps/app-lifeops/src/lifeops/service-mixin-core.d.ts.map +1 -1
  187. package/apps/app-lifeops/src/lifeops/service-mixin-core.js +2 -1
  188. package/apps/app-lifeops/src/lifeops/service-mixin-imessage.js +1 -1
  189. package/apps/app-lifeops/src/lifeops/service-mixin-inbox.d.ts +3 -1
  190. package/apps/app-lifeops/src/lifeops/service-mixin-inbox.d.ts.map +1 -1
  191. package/apps/app-lifeops/src/lifeops/service-mixin-inbox.js +42 -13
  192. package/apps/app-lifeops/src/lifeops/service-mixin-reminders.d.ts.map +1 -1
  193. package/apps/app-lifeops/src/lifeops/service-mixin-reminders.js +3 -2
  194. package/apps/app-lifeops/src/lifeops/service-mixin-workflows.d.ts.map +1 -1
  195. package/apps/app-lifeops/src/lifeops/service-mixin-workflows.js +1 -1
  196. package/apps/app-lifeops/src/lifeops/service-normalize-calendar.d.ts.map +1 -1
  197. package/apps/app-lifeops/src/lifeops/service-normalize-calendar.js +3 -3
  198. package/apps/app-lifeops/src/lifeops/service-normalize-connector.d.ts +1 -1
  199. package/apps/app-lifeops/src/lifeops/service-normalize-connector.d.ts.map +1 -1
  200. package/apps/app-lifeops/src/lifeops/service-normalize-connector.js +2 -2
  201. package/apps/app-lifeops/src/lifeops/signal-auth.d.ts.map +1 -1
  202. package/apps/app-lifeops/src/lifeops/signal-auth.js +6 -3
  203. package/apps/app-lifeops/src/lifeops/telegram-auth.js +1 -1
  204. package/apps/app-lifeops/src/lifeops/travel-adapters/duffel.d.ts.map +1 -1
  205. package/apps/app-lifeops/src/lifeops/travel-adapters/duffel.js +31 -6
  206. package/apps/app-lifeops/src/lifeops/twilio.js +1 -1
  207. package/apps/app-lifeops/src/lifeops/x-poster.d.ts.map +1 -1
  208. package/apps/app-lifeops/src/lifeops/x-poster.js +13 -3
  209. package/apps/app-lifeops/src/lifeops-route.d.ts +74 -0
  210. package/apps/app-lifeops/src/lifeops-route.d.ts.map +1 -0
  211. package/apps/app-lifeops/src/lifeops-route.js +204 -0
  212. package/apps/app-lifeops/src/platform/lifeops-github.d.ts +15 -0
  213. package/apps/app-lifeops/src/platform/lifeops-github.d.ts.map +1 -0
  214. package/apps/app-lifeops/src/platform/lifeops-github.js +135 -0
  215. package/apps/app-lifeops/src/routes/cloud-features-routes.d.ts +2 -2
  216. package/apps/app-lifeops/src/routes/cloud-features-routes.d.ts.map +1 -1
  217. package/apps/app-lifeops/src/routes/cloud-features-routes.js +5 -3
  218. package/apps/app-lifeops/src/routes/lifeops-routes.d.ts.map +1 -1
  219. package/apps/app-lifeops/src/routes/lifeops-routes.js +15 -3
  220. package/apps/app-lifeops/src/routes/plugin.d.ts.map +1 -1
  221. package/apps/app-lifeops/src/routes/plugin.js +10 -1
  222. package/apps/app-lifeops/src/routes/travel-provider-relay-routes.d.ts +1 -1
  223. package/apps/app-lifeops/src/routes/travel-provider-relay-routes.d.ts.map +1 -1
  224. package/apps/app-lifeops/src/routes/travel-provider-relay-routes.js +4 -2
  225. package/apps/app-lifeops/src/routes/website-blocker-routes.d.ts +1 -1
  226. package/apps/app-lifeops/src/routes/website-blocker-routes.d.ts.map +1 -1
  227. package/apps/app-lifeops/src/ui.d.ts +11 -0
  228. package/apps/app-lifeops/src/ui.d.ts.map +1 -0
  229. package/apps/app-lifeops/src/ui.js +9 -0
  230. package/apps/app-lifeops/src/utils/lifeops-url.d.ts +5 -0
  231. package/apps/app-lifeops/src/utils/lifeops-url.d.ts.map +1 -0
  232. package/apps/app-lifeops/src/utils/lifeops-url.js +35 -0
  233. package/apps/app-lifeops/src/website-blocker/access.d.ts.map +1 -1
  234. package/apps/app-lifeops/src/website-blocker/access.js +1 -1
  235. package/apps/app-steward/src/routes/steward-compat-routes.d.ts +1 -1
  236. package/apps/app-steward/src/routes/steward-compat-routes.d.ts.map +1 -1
  237. package/apps/app-steward/src/routes/steward-compat-routes.js +3 -1
  238. package/apps/app-steward/src/routes/wallet-browser-compat-routes.d.ts +1 -1
  239. package/apps/app-steward/src/routes/wallet-browser-compat-routes.d.ts.map +1 -1
  240. package/apps/app-steward/src/routes/wallet-browser-compat-routes.js +3 -1
  241. package/apps/app-steward/src/routes/wallet-bsc-core-routes.d.ts.map +1 -1
  242. package/apps/app-steward/src/routes/wallet-bsc-core-routes.js +2 -1
  243. package/apps/app-steward/src/routes/wallet-compat-routes.d.ts +1 -1
  244. package/apps/app-steward/src/routes/wallet-compat-routes.d.ts.map +1 -1
  245. package/apps/app-steward/src/routes/wallet-compat-routes.js +3 -1
  246. package/apps/app-steward/src/routes/wallet-core-routes.d.ts.map +1 -1
  247. package/apps/app-steward/src/routes/wallet-core-routes.js +2 -1
  248. package/apps/app-steward/src/routes/wallet-trade-compat-routes.d.ts +1 -1
  249. package/apps/app-steward/src/routes/wallet-trade-compat-routes.d.ts.map +1 -1
  250. package/apps/app-steward/src/routes/wallet-trade-compat-routes.js +3 -1
  251. package/apps/app-training/src/core/dataset-generator.d.ts +1 -1
  252. package/apps/app-training/src/core/dataset-generator.d.ts.map +1 -1
  253. package/apps/app-training/src/core/roleplay-executor.d.ts +1 -1
  254. package/apps/app-training/src/core/roleplay-executor.d.ts.map +1 -1
  255. package/apps/app-training/src/core/trajectory-task-datasets.d.ts +1 -1
  256. package/apps/app-training/src/core/trajectory-task-datasets.d.ts.map +1 -1
  257. package/apps/app-training/src/index.d.ts +1 -2
  258. package/apps/app-training/src/index.d.ts.map +1 -1
  259. package/apps/app-training/src/index.js +1 -2
  260. package/apps/app-training/src/routes/training-routes.d.ts +1 -1
  261. package/apps/app-training/src/routes/training-routes.d.ts.map +1 -1
  262. package/apps/app-training/src/routes/training-routes.js +1 -1
  263. package/apps/app-training/src/routes/trajectory-routes.d.ts +1 -1
  264. package/apps/app-training/src/routes/trajectory-routes.d.ts.map +1 -1
  265. package/apps/app-training/src/routes/trajectory-routes.js +3 -1
  266. package/apps/app-training/src/services/training-service-like.d.ts +1 -1
  267. package/apps/app-training/src/services/training-service-like.d.ts.map +1 -1
  268. package/apps/app-training/src/services/training-service.d.ts +1 -1
  269. package/apps/app-training/src/services/training-service.d.ts.map +1 -1
  270. package/package.json +4 -4
  271. package/packages/agent/src/api/provider-switch-config.js +1 -1
  272. package/packages/agent/src/api/server-helpers-auth.d.ts.map +1 -1
  273. package/packages/agent/src/api/server-helpers-auth.js +5 -4
  274. package/packages/agent/src/providers/media-provider.d.ts +1 -1
  275. package/packages/agent/src/providers/media-provider.d.ts.map +1 -1
  276. package/packages/agent/src/providers/self-status.d.ts +1 -1
  277. package/packages/agent/src/providers/self-status.d.ts.map +1 -1
  278. package/packages/app-core/src/App.d.ts.map +1 -1
  279. package/packages/app-core/src/App.js +20 -12
  280. package/packages/app-core/src/api/auth.d.ts.map +1 -1
  281. package/packages/app-core/src/api/auth.js +5 -5
  282. package/packages/app-core/src/api/client-types-experience.d.ts +7 -0
  283. package/packages/app-core/src/api/client-types-experience.d.ts.map +1 -1
  284. package/packages/app-core/src/components/apps/helpers.d.ts +1 -1
  285. package/packages/app-core/src/components/apps/helpers.d.ts.map +1 -1
  286. package/packages/app-core/src/components/apps/helpers.js +1 -0
  287. package/packages/app-core/src/components/apps/internal-tool-apps.d.ts +11 -0
  288. package/packages/app-core/src/components/apps/internal-tool-apps.d.ts.map +1 -1
  289. package/packages/app-core/src/components/apps/internal-tool-apps.js +31 -0
  290. package/packages/app-core/src/components/apps/launch-history.d.ts +16 -0
  291. package/packages/app-core/src/components/apps/launch-history.d.ts.map +1 -0
  292. package/packages/app-core/src/components/apps/launch-history.js +77 -0
  293. package/packages/app-core/src/components/apps/per-app-config.d.ts +19 -0
  294. package/packages/app-core/src/components/apps/per-app-config.d.ts.map +1 -0
  295. package/packages/app-core/src/components/apps/per-app-config.js +99 -0
  296. package/packages/app-core/src/components/apps/useRegistryCatalog.d.ts +14 -0
  297. package/packages/app-core/src/components/apps/useRegistryCatalog.d.ts.map +1 -0
  298. package/packages/app-core/src/components/apps/useRegistryCatalog.js +52 -0
  299. package/packages/app-core/src/components/auth/LoginView.d.ts +1 -19
  300. package/packages/app-core/src/components/auth/LoginView.d.ts.map +1 -1
  301. package/packages/app-core/src/components/auth/LoginView.js +4 -99
  302. package/packages/app-core/src/components/character/CharacterExperienceWorkspace.d.ts.map +1 -1
  303. package/packages/app-core/src/components/character/CharacterExperienceWorkspace.js +14 -2
  304. package/packages/app-core/src/components/character/character-hub-helpers.d.ts.map +1 -1
  305. package/packages/app-core/src/components/character/character-hub-helpers.js +7 -0
  306. package/packages/app-core/src/components/character/character-hub-types.d.ts +7 -0
  307. package/packages/app-core/src/components/character/character-hub-types.d.ts.map +1 -1
  308. package/packages/app-core/src/components/onboarding/BootstrapStep.d.ts.map +1 -1
  309. package/packages/app-core/src/components/onboarding/BootstrapStep.js +3 -2
  310. package/packages/app-core/src/components/pages/AppDetailsView.d.ts +36 -0
  311. package/packages/app-core/src/components/pages/AppDetailsView.d.ts.map +1 -0
  312. package/packages/app-core/src/components/pages/AppDetailsView.js +289 -0
  313. package/packages/app-core/src/components/pages/AppsView.d.ts.map +1 -1
  314. package/packages/app-core/src/components/pages/AppsView.js +134 -42
  315. package/packages/app-core/src/components/shell/StartupShell.d.ts.map +1 -1
  316. package/packages/app-core/src/components/shell/StartupShell.js +2 -5
  317. package/packages/app-core/src/i18n/locales/en.json +256 -205
  318. package/packages/app-core/src/i18n/locales/es.json +256 -205
  319. package/packages/app-core/src/i18n/locales/ko.json +256 -205
  320. package/packages/app-core/src/i18n/locales/pt.json +256 -205
  321. package/packages/app-core/src/i18n/locales/tl.json +256 -205
  322. package/packages/app-core/src/i18n/locales/vi.json +256 -205
  323. package/packages/app-core/src/i18n/locales/zh-CN.json +256 -205
  324. package/packages/app-core/src/navigation/index.d.ts.map +1 -1
  325. package/packages/app-core/src/navigation/index.js +6 -0
  326. package/packages/app-core/src/shell/AppWindowRenderer.d.ts +17 -0
  327. package/packages/app-core/src/shell/AppWindowRenderer.d.ts.map +1 -0
  328. package/packages/app-core/src/shell/AppWindowRenderer.js +337 -0
  329. package/packages/app-core/src/shell/DetachedShellRoot.js +4 -1
  330. package/packages/app-core/src/shell/index.d.ts +1 -0
  331. package/packages/app-core/src/shell/index.d.ts.map +1 -1
  332. package/packages/app-core/src/shell/index.js +1 -0
  333. package/packages/app-core/src/state/startup-coordinator.d.ts.map +1 -1
  334. package/packages/app-core/src/state/startup-coordinator.js +0 -3
  335. package/packages/app-core/src/state/startup-phase-poll.d.ts.map +1 -1
  336. package/packages/app-core/src/state/startup-phase-poll.js +2 -4
  337. package/packages/app-core/src/state/usePluginsSkillsState.d.ts +6 -6
  338. package/packages/native-plugins/mobile-signals/src/definitions.d.ts +162 -0
  339. package/packages/native-plugins/mobile-signals/src/definitions.d.ts.map +1 -0
  340. package/packages/native-plugins/mobile-signals/src/definitions.js +1 -0
  341. package/packages/native-plugins/mobile-signals/src/index.d.ts +4 -0
  342. package/packages/native-plugins/mobile-signals/src/index.d.ts.map +1 -0
  343. package/packages/native-plugins/mobile-signals/src/index.js +6 -0
  344. package/packages/native-plugins/mobile-signals/src/web.d.ts +29 -0
  345. package/packages/native-plugins/mobile-signals/src/web.d.ts.map +1 -0
  346. package/packages/native-plugins/mobile-signals/src/web.js +269 -0
  347. package/packages/shared/src/app-hero-art.d.ts.map +1 -1
  348. package/packages/shared/src/app-hero-art.js +13 -0
  349. package/packages/shared/src/contracts/lifeops.d.ts +10 -0
  350. package/packages/shared/src/contracts/lifeops.d.ts.map +1 -1
  351. package/packages/shared/src/contracts/lifeops.js +5 -0
  352. package/packages/typescript/src/features/advanced-capabilities/experience/actions/record-experience.d.ts.map +1 -1
  353. package/packages/typescript/src/features/advanced-capabilities/experience/actions/record-experience.js +46 -4
  354. package/packages/typescript/src/features/advanced-capabilities/experience/evaluators/experienceEvaluator.d.ts.map +1 -1
  355. package/packages/typescript/src/features/advanced-capabilities/experience/evaluators/experienceEvaluator.js +34 -124
  356. package/packages/typescript/src/features/advanced-capabilities/experience/service.d.ts.map +1 -1
  357. package/packages/typescript/src/features/advanced-capabilities/experience/service.js +56 -0
  358. package/packages/typescript/src/features/advanced-capabilities/experience/types.d.ts +7 -0
  359. package/packages/typescript/src/features/advanced-capabilities/experience/types.d.ts.map +1 -1
  360. package/packages/typescript/src/features/advanced-capabilities/experience/utils/experienceText.d.ts +7 -0
  361. package/packages/typescript/src/features/advanced-capabilities/experience/utils/experienceText.d.ts.map +1 -0
  362. package/packages/typescript/src/features/advanced-capabilities/experience/utils/experienceText.js +123 -0
  363. package/apps/app-training/src/ui/FineTuningView.d.ts +0 -5
  364. package/apps/app-training/src/ui/FineTuningView.d.ts.map +0 -1
  365. package/apps/app-training/src/ui/FineTuningView.js +0 -388
  366. package/apps/app-training/src/ui/fine-tuning-panels.d.ts +0 -111
  367. package/apps/app-training/src/ui/fine-tuning-panels.d.ts.map +0 -1
  368. package/apps/app-training/src/ui/fine-tuning-panels.js +0 -130
  369. package/apps/app-training/src/ui/index.d.ts +0 -3
  370. package/apps/app-training/src/ui/index.d.ts.map +0 -1
  371. package/apps/app-training/src/ui/index.js +0 -2
  372. package/packages/app-core/src/api/trusted-local-request.d.ts +0 -4
  373. package/packages/app-core/src/api/trusted-local-request.d.ts.map +0 -1
  374. package/packages/app-core/src/api/trusted-local-request.js +0 -176
@@ -0,0 +1,1065 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Badge, Button, client, copyTextToClipboard, Input, invokeDesktopBridgeRequest, isElectrobunRuntime, Label, navigatePreOpenedWindow, openExternalUrl, preOpenWindow, SegmentedControl, Switch, Textarea, useApp, } from "@elizaos/app-core";
3
+ import { BROWSER_BRIDGE_SITE_ACCESS_MODES, } from "../contracts/index.js";
4
+ import { CheckCircle2, Circle, Copy, Download, ExternalLink, FolderOpen, Monitor, Package, RefreshCw, ShieldCheck, Sparkles, } from "lucide-react";
5
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
6
+ import { resolveBrowserBridgeApiBaseUrl } from "../utils/lifeops-url.js";
7
+ const DEFAULT_PAIRING_PROFILE = {
8
+ profileId: "default",
9
+ profileLabel: "Default",
10
+ };
11
+ const CHROME_EXTENSIONS_URL = "chrome://extensions/";
12
+ const CONNECTION_REFRESH_INTERVAL_MS = 4_000;
13
+ const BROWSER_SETUP_HASH = "lifeops.section=setup";
14
+ function isIosRuntime() {
15
+ if (typeof navigator !== "undefined" &&
16
+ /iPad|iPhone|iPod/.test(navigator.userAgent)) {
17
+ return true;
18
+ }
19
+ const capacitor = globalThis.Capacitor;
20
+ return capacitor?.getPlatform?.() === "ios";
21
+ }
22
+ function detectRuntimeBrowserKind() {
23
+ if (typeof navigator === "undefined") {
24
+ return null;
25
+ }
26
+ const userAgent = navigator.userAgent.toLowerCase();
27
+ const vendor = navigator.vendor?.toLowerCase() ?? "";
28
+ const chromeFamily = userAgent.includes("chrome") ||
29
+ userAgent.includes("chromium") ||
30
+ userAgent.includes("crios") ||
31
+ userAgent.includes("edg/") ||
32
+ userAgent.includes("brave");
33
+ if (chromeFamily) {
34
+ return "chrome";
35
+ }
36
+ if (vendor.includes("apple") && userAgent.includes("safari")) {
37
+ return "safari";
38
+ }
39
+ return null;
40
+ }
41
+ function settingsToDraft(settings) {
42
+ return {
43
+ enabled: settings.enabled,
44
+ trackingMode: settings.trackingMode,
45
+ allowBrowserControl: settings.allowBrowserControl,
46
+ requireConfirmationForAccountAffecting: settings.requireConfirmationForAccountAffecting,
47
+ incognitoEnabled: settings.incognitoEnabled,
48
+ siteAccessMode: settings.siteAccessMode,
49
+ grantedOriginsText: settings.grantedOrigins.join("\n"),
50
+ blockedOriginsText: settings.blockedOrigins.join("\n"),
51
+ maxRememberedTabs: String(settings.maxRememberedTabs),
52
+ pauseUntilLocal: formatDateTimeLocalValue(settings.pauseUntil),
53
+ };
54
+ }
55
+ function parseOriginLines(value) {
56
+ return value
57
+ .split(/\r?\n/)
58
+ .map((entry) => entry.trim().replace(/\/+$/, ""))
59
+ .filter((entry) => entry.length > 0);
60
+ }
61
+ function formatDateTimeLocalValue(value) {
62
+ if (!value) {
63
+ return "";
64
+ }
65
+ const parsed = Date.parse(value);
66
+ if (!Number.isFinite(parsed)) {
67
+ return "";
68
+ }
69
+ const date = new Date(parsed);
70
+ const year = String(date.getFullYear());
71
+ const month = String(date.getMonth() + 1).padStart(2, "0");
72
+ const day = String(date.getDate()).padStart(2, "0");
73
+ const hours = String(date.getHours()).padStart(2, "0");
74
+ const minutes = String(date.getMinutes()).padStart(2, "0");
75
+ return `${year}-${month}-${day}T${hours}:${minutes}`;
76
+ }
77
+ function parseDateTimeLocalValue(value) {
78
+ const trimmed = value.trim();
79
+ if (!trimmed) {
80
+ return null;
81
+ }
82
+ const parsed = new Date(trimmed);
83
+ if (!Number.isFinite(parsed.getTime())) {
84
+ throw new Error("Pause until must be a valid local date and time");
85
+ }
86
+ return parsed.toISOString();
87
+ }
88
+ function settingsRequestFromDraft(draft) {
89
+ return {
90
+ enabled: draft.enabled,
91
+ trackingMode: draft.trackingMode,
92
+ allowBrowserControl: draft.allowBrowserControl,
93
+ requireConfirmationForAccountAffecting: draft.requireConfirmationForAccountAffecting,
94
+ incognitoEnabled: draft.incognitoEnabled,
95
+ siteAccessMode: draft.siteAccessMode,
96
+ grantedOrigins: parseOriginLines(draft.grantedOriginsText),
97
+ blockedOrigins: parseOriginLines(draft.blockedOriginsText),
98
+ maxRememberedTabs: Math.max(1, Number.parseInt(draft.maxRememberedTabs, 10) || 10),
99
+ pauseUntil: parseDateTimeLocalValue(draft.pauseUntilLocal),
100
+ };
101
+ }
102
+ function isFutureLocalDateTimeValue(value) {
103
+ const trimmed = value.trim();
104
+ if (!trimmed) {
105
+ return false;
106
+ }
107
+ const parsed = new Date(trimmed);
108
+ return Number.isFinite(parsed.getTime()) && parsed.getTime() > Date.now();
109
+ }
110
+ function normalizePairingRequest(browser, existing) {
111
+ return {
112
+ browser,
113
+ profileId: existing?.profileId || DEFAULT_PAIRING_PROFILE.profileId,
114
+ profileLabel: existing?.profileLabel || DEFAULT_PAIRING_PROFILE.profileLabel,
115
+ label: existing?.label ||
116
+ `Agent Browser Bridge ${browser} ${existing?.profileLabel || DEFAULT_PAIRING_PROFILE.profileLabel}`,
117
+ };
118
+ }
119
+ function pairingPayload(response) {
120
+ return {
121
+ apiBaseUrl: resolveBrowserBridgeApiBaseUrl(),
122
+ companionId: response.companion.id,
123
+ pairingToken: response.pairingToken,
124
+ browser: response.companion.browser,
125
+ profileId: response.companion.profileId,
126
+ profileLabel: response.companion.profileLabel,
127
+ label: response.companion.label,
128
+ };
129
+ }
130
+ async function openDesktopPath(pathValue, revealOnly = false) {
131
+ await invokeDesktopBridgeRequest({
132
+ rpcMethod: revealOnly ? "desktopShowItemInFolder" : "desktopOpenPath",
133
+ ipcChannel: revealOnly ? "desktop:showItemInFolder" : "desktop:openPath",
134
+ params: { path: pathValue },
135
+ });
136
+ }
137
+ function formatTimestamp(value) {
138
+ if (!value) {
139
+ return null;
140
+ }
141
+ const parsed = Date.parse(value);
142
+ if (!Number.isFinite(parsed)) {
143
+ return null;
144
+ }
145
+ return new Intl.DateTimeFormat(undefined, {
146
+ month: "short",
147
+ day: "numeric",
148
+ hour: "numeric",
149
+ minute: "2-digit",
150
+ }).format(new Date(parsed));
151
+ }
152
+ function permissionSummary(permissions) {
153
+ if (!permissions) {
154
+ return "Permissions unavailable";
155
+ }
156
+ return [
157
+ permissions.allOrigins
158
+ ? "all-sites access"
159
+ : permissions.grantedOrigins.length > 0
160
+ ? `${permissions.grantedOrigins.length} granted site${permissions.grantedOrigins.length === 1 ? "" : "s"}`
161
+ : "current-site access",
162
+ permissions.scripting ? "DOM actions enabled" : "DOM actions unavailable",
163
+ permissions.incognitoEnabled ? "incognito on" : "incognito off",
164
+ ].join(" • ");
165
+ }
166
+ function mergePackageStatus(current, next) {
167
+ return {
168
+ relayReachable: current?.relayReachable ?? false,
169
+ relayPort: current?.relayPort ?? 18792,
170
+ extensionPath: next.extensionPath,
171
+ chromeBuildPath: next.chromeBuildPath,
172
+ chromePackagePath: next.chromePackagePath,
173
+ safariWebExtensionPath: next.safariWebExtensionPath,
174
+ safariAppPath: next.safariAppPath,
175
+ safariPackagePath: next.safariPackagePath,
176
+ releaseManifest: next.releaseManifest ?? null,
177
+ };
178
+ }
179
+ function releaseTargetForBrowser(browser, releaseManifest) {
180
+ if (!releaseManifest) {
181
+ return null;
182
+ }
183
+ return browser === "chrome" ? releaseManifest.chrome : releaseManifest.safari;
184
+ }
185
+ function installButtonLabel(browser, releaseManifest, options) {
186
+ const { hasLocalArtifact, localWorkspaceAvailable } = options;
187
+ if (localWorkspaceAvailable) {
188
+ if (!hasLocalArtifact) {
189
+ return `Build & Install in ${browser === "chrome" ? "Chrome" : "Safari"}`;
190
+ }
191
+ return browser === "chrome" ? "Install in Chrome" : "Install in Safari";
192
+ }
193
+ const target = releaseTargetForBrowser(browser, releaseManifest);
194
+ if (target?.installKind === "chrome_web_store") {
195
+ return "Open Chrome Web Store";
196
+ }
197
+ if (target?.installKind === "apple_app_store") {
198
+ return "Open App Store";
199
+ }
200
+ if (target?.installKind === "github_release") {
201
+ return `Download ${browser === "chrome" ? "Chrome" : "Safari"} Release`;
202
+ }
203
+ if (target?.installKind === "local_download") {
204
+ return `Download ${browser === "chrome" ? "Chrome" : "Safari"} Package`;
205
+ }
206
+ return `Install ${browser === "chrome" ? "Chrome" : "Safari"} Extension`;
207
+ }
208
+ function trackingModeLabel(mode) {
209
+ switch (mode) {
210
+ case "current_tab":
211
+ return "Current tab";
212
+ case "active_tabs":
213
+ return "Active tabs";
214
+ default:
215
+ return "Off";
216
+ }
217
+ }
218
+ function siteAccessModeLabel(mode) {
219
+ switch (mode) {
220
+ case "current_site_only":
221
+ return "Current site";
222
+ case "granted_sites":
223
+ return "Granted sites";
224
+ default:
225
+ return "All sites";
226
+ }
227
+ }
228
+ function BrowserSettingRow({ checked, hint, label, onCheckedChange, }) {
229
+ return (_jsxs("div", { className: "flex items-center justify-between gap-3 py-2.5", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-sm text-txt", children: label }), hint ? _jsx("div", { className: "mt-0.5 text-xs text-muted", children: hint }) : null] }), _jsx(Switch, { checked: checked, onCheckedChange: onCheckedChange })] }));
230
+ }
231
+ function releaseBadgeLabel(browser, releaseManifest, localWorkspaceAvailable) {
232
+ if (localWorkspaceAvailable) {
233
+ return "Local build";
234
+ }
235
+ const target = releaseTargetForBrowser(browser, releaseManifest);
236
+ if (!target) {
237
+ return null;
238
+ }
239
+ if (target.installKind === "chrome_web_store") {
240
+ return "Chrome Web Store";
241
+ }
242
+ if (target.installKind === "apple_app_store") {
243
+ return "App Store";
244
+ }
245
+ if (target.installKind === "github_release") {
246
+ return "Release build";
247
+ }
248
+ return "Download";
249
+ }
250
+ function buildStateBadgeLabel(hasLocalArtifact, localWorkspaceAvailable) {
251
+ if (hasLocalArtifact) {
252
+ return "Built";
253
+ }
254
+ if (localWorkspaceAvailable) {
255
+ return "Build on install";
256
+ }
257
+ return "Download";
258
+ }
259
+ function BridgeDot({ label, tone, }) {
260
+ const className = tone === "ok"
261
+ ? "bg-emerald-500 shadow-[0_0_0_3px_rgba(16,185,129,0.14)]"
262
+ : tone === "warning"
263
+ ? "bg-amber-500 shadow-[0_0_0_3px_rgba(245,158,11,0.14)]"
264
+ : "bg-muted/45";
265
+ return (_jsx("span", { "aria-label": label, className: `inline-block h-2.5 w-2.5 shrink-0 rounded-full ${className}`, role: "img", title: label }));
266
+ }
267
+ function BridgeMeter({ connected, total, }) {
268
+ const safeTotal = Math.max(total, 0);
269
+ const width = safeTotal > 0
270
+ ? `${(Math.min(Math.max(connected, 0), safeTotal) / safeTotal) * 100}%`
271
+ : "0%";
272
+ return (_jsx("span", { "aria-label": `${connected}/${total} browser profiles connected`, className: "inline-flex h-1.5 w-16 overflow-hidden rounded-full bg-bg/70", role: "img", title: `${connected}/${total} browser profiles connected`, children: _jsx("span", { className: "h-full rounded-full bg-emerald-500", style: { width } }) }));
273
+ }
274
+ function installHint(browser, currentBrowser, localWorkspaceAvailable, releaseManifest) {
275
+ if (localWorkspaceAvailable) {
276
+ if (browser === "chrome") {
277
+ return currentBrowser === "chrome"
278
+ ? "Install builds the extension, opens chrome://extensions in this browser profile when possible, and reveals the folder for Load unpacked."
279
+ : "Install builds the extension, opens Chrome extensions, and reveals the folder you need for Load unpacked.";
280
+ }
281
+ return "Install builds the Safari helper app and opens it so you can enable the extension once.";
282
+ }
283
+ const target = releaseTargetForBrowser(browser, releaseManifest);
284
+ if (target?.installKind === "chrome_web_store") {
285
+ return "Use the published Chrome Web Store build, then open the popup once in the profile you want LifeOps to use.";
286
+ }
287
+ if (target?.installKind === "apple_app_store") {
288
+ return "Use the published Safari App Store build, then enable the extension and open its popup once.";
289
+ }
290
+ return "Download the published browser companion, install it, then open the popup once to auto-connect.";
291
+ }
292
+ function statusLabel(status) {
293
+ switch (status) {
294
+ case "done":
295
+ return "Done";
296
+ case "current":
297
+ return "Next";
298
+ case "attention":
299
+ return "Check";
300
+ default:
301
+ return "Pending";
302
+ }
303
+ }
304
+ function recommendedBrowserKind(currentBrowser) {
305
+ return currentBrowser ?? "chrome";
306
+ }
307
+ function browserLabel(browser) {
308
+ return browser === "safari" ? "Safari" : "Chrome";
309
+ }
310
+ function browserSettingsReady(draft) {
311
+ return Boolean(draft?.enabled &&
312
+ draft.trackingMode !== "off" &&
313
+ draft.allowBrowserControl &&
314
+ !isFutureLocalDateTimeValue(draft.pauseUntilLocal));
315
+ }
316
+ function buildSetupUrl() {
317
+ if (typeof window === "undefined") {
318
+ return null;
319
+ }
320
+ try {
321
+ const url = new URL(window.location.href);
322
+ url.hash = BROWSER_SETUP_HASH;
323
+ return url.toString();
324
+ }
325
+ catch {
326
+ return window.location.href || null;
327
+ }
328
+ }
329
+ function hasBrowserArtifact(browser, status) {
330
+ if (!status) {
331
+ return false;
332
+ }
333
+ return browser === "chrome"
334
+ ? Boolean(status.chromeBuildPath || status.chromePackagePath)
335
+ : Boolean(status.safariAppPath ||
336
+ status.safariPackagePath ||
337
+ status.safariWebExtensionPath);
338
+ }
339
+ function companionPermissionReady(companion) {
340
+ if (!companion?.permissions) {
341
+ return false;
342
+ }
343
+ return (companion.permissions.tabs &&
344
+ companion.permissions.scripting &&
345
+ companion.permissions.activeTab &&
346
+ companion.permissions.allOrigins);
347
+ }
348
+ function BrowserCompanionRow({ currentBrowser, browser, buildPath, packagePath, appPath, localWorkspaceAvailable, releaseManifest, busy, pairing, onInstall, onBuild, onCreatePairing, onCopyPairing, onDownload, onOpenTarget, onOpenManager, }) {
349
+ const browserLabel = browser === "chrome" ? "Chrome" : "Safari";
350
+ const distributionLabel = releaseBadgeLabel(browser, releaseManifest, localWorkspaceAvailable);
351
+ const hasLocalArtifact = Boolean(buildPath || packagePath || appPath);
352
+ const installLabel = installButtonLabel(browser, releaseManifest, {
353
+ hasLocalArtifact,
354
+ localWorkspaceAvailable,
355
+ });
356
+ const buildBadgeLabel = buildStateBadgeLabel(hasLocalArtifact, localWorkspaceAvailable);
357
+ const rowHint = installHint(browser, currentBrowser, localWorkspaceAvailable, releaseManifest);
358
+ return (_jsxs("div", { className: "space-y-2 rounded-2xl bg-card/16 p-3", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(Badge, { variant: "outline", children: browserLabel }), currentBrowser === browser ? (_jsx(Badge, { variant: "secondary", className: "text-2xs", children: "This Browser" })) : null, distributionLabel ? (_jsx(Badge, { variant: "secondary", className: "text-2xs", children: distributionLabel })) : null, hasLocalArtifact || localWorkspaceAvailable ? (_jsx(Badge, { variant: "secondary", className: "text-2xs", children: buildBadgeLabel })) : (_jsx(Badge, { variant: "outline", className: "text-2xs", children: "Download" }))] }), _jsx("div", { className: "text-xs leading-relaxed text-muted", children: rowHint }), _jsxs("div", { className: "flex flex-wrap gap-1.5", children: [_jsxs(Button, { size: "sm", disabled: busy, onClick: () => void onInstall(browser), children: [_jsx(Sparkles, { className: "mr-1.5 h-3 w-3" }), busy ? "…" : installLabel] }), _jsxs(Button, { size: "sm", variant: "outline", disabled: busy, onClick: () => void onBuild(browser), children: [_jsx(Package, { className: "mr-1.5 h-3 w-3" }), "Build"] }), _jsx(Button, { size: "sm", variant: "outline", disabled: busy, onClick: () => void onCreatePairing(browser), children: "Manual Pairing" }), browser === "chrome" && buildPath ? (_jsxs(_Fragment, { children: [_jsxs(Button, { size: "sm", variant: "outline", disabled: busy, onClick: () => void onOpenTarget("chrome_build", true), children: [_jsx(FolderOpen, { className: "mr-1.5 h-3 w-3" }), "Open Folder"] }), _jsx(Button, { size: "sm", variant: "outline", disabled: busy, onClick: () => void onOpenManager("chrome"), children: "Open Extensions" })] })) : null, pairing ? (_jsxs(Button, { size: "sm", variant: "outline", disabled: busy, onClick: () => void onCopyPairing(browser), children: [_jsx(Copy, { className: "mr-1.5 h-3 w-3" }), "Copy"] })) : null, packagePath ? (_jsxs(Button, { size: "sm", variant: "outline", disabled: busy, onClick: () => void onDownload(browser), children: [_jsx(Download, { className: "mr-1.5 h-3 w-3" }), "Zip"] })) : null] }), buildPath || packagePath || appPath ? (_jsxs("div", { className: "space-y-1 text-xs text-muted", children: [buildPath ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-semibold text-txt", children: "Build:" }), _jsx("span", { className: "min-w-0 truncate font-mono", children: buildPath }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => void onOpenTarget(browser === "chrome"
359
+ ? "chrome_build"
360
+ : "safari_web_extension", true), children: "Open Folder" })] })) : null, packagePath ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-semibold text-txt", children: "Pkg:" }), _jsx("span", { className: "min-w-0 truncate font-mono", children: packagePath }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => void onOpenTarget(browser === "chrome" ? "chrome_package" : "safari_package", true), children: "Reveal Zip" })] })) : null, appPath ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-semibold text-txt", children: "App:" }), _jsx("span", { className: "min-w-0 truncate font-mono", children: appPath }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => void onOpenTarget("safari_app"), children: "Open" }), _jsxs(Button, { size: "sm", variant: "outline", onClick: () => void onOpenTarget("safari_app", true), children: [_jsx(FolderOpen, { className: "mr-1.5 h-3 w-3" }), "Show in Folder"] })] })) : null] })) : null] }));
361
+ }
362
+ export function BrowserBridgeSetupPanel() {
363
+ const { setActionNotice, setTab } = useApp();
364
+ const currentBrowser = useMemo(() => detectRuntimeBrowserKind(), []);
365
+ const [draft, setDraft] = useState(null);
366
+ const [draftDirty, setDraftDirty] = useState(false);
367
+ const draftRef = useRef(null);
368
+ const draftDirtyRef = useRef(false);
369
+ const [companions, setCompanions] = useState([]);
370
+ const [packageStatus, setPackageStatus] = useState(null);
371
+ const [pairings, setPairings] = useState({});
372
+ const [loading, setLoading] = useState(true);
373
+ const [savingSettings, setSavingSettings] = useState(false);
374
+ const [buildingBrowser, setBuildingBrowser] = useState(null);
375
+ const [pairingBrowser, setPairingBrowser] = useState(null);
376
+ const [installingBrowser, setInstallingBrowser] = useState(null);
377
+ const [statusMessage, setStatusMessage] = useState(null);
378
+ const [error, setError] = useState(null);
379
+ useEffect(() => {
380
+ draftRef.current = draft;
381
+ }, [draft]);
382
+ useEffect(() => {
383
+ draftDirtyRef.current = draftDirty;
384
+ }, [draftDirty]);
385
+ const refresh = useCallback(async (options) => {
386
+ setLoading(true);
387
+ setError(null);
388
+ const [settingsResult, companionsResult, statusResult] = await Promise.allSettled([
389
+ client.getBrowserBridgeSettings(),
390
+ client.listBrowserBridgeCompanions(),
391
+ client.getBrowserBridgePackageStatus(),
392
+ ]);
393
+ const errors = [];
394
+ if (settingsResult.status === "fulfilled") {
395
+ if (!options?.preserveDraft ||
396
+ !draftDirtyRef.current ||
397
+ !draftRef.current) {
398
+ setDraft(settingsToDraft(settingsResult.value.settings));
399
+ setDraftDirty(false);
400
+ }
401
+ }
402
+ else {
403
+ errors.push(settingsResult.reason instanceof Error
404
+ ? settingsResult.reason.message
405
+ : String(settingsResult.reason));
406
+ }
407
+ if (companionsResult.status === "fulfilled") {
408
+ setCompanions(companionsResult.value.companions);
409
+ }
410
+ else {
411
+ errors.push(companionsResult.reason instanceof Error
412
+ ? companionsResult.reason.message
413
+ : String(companionsResult.reason));
414
+ }
415
+ if (statusResult.status === "fulfilled") {
416
+ setPackageStatus((current) => mergePackageStatus(current, statusResult.value.status));
417
+ }
418
+ else {
419
+ errors.push(statusResult.reason instanceof Error
420
+ ? statusResult.reason.message
421
+ : String(statusResult.reason));
422
+ }
423
+ if (errors.length > 0) {
424
+ setError(errors[0]);
425
+ }
426
+ setLoading(false);
427
+ }, []);
428
+ useEffect(() => {
429
+ void refresh();
430
+ }, [refresh]);
431
+ useEffect(() => {
432
+ const timer = window.setInterval(() => {
433
+ void refresh({ preserveDraft: true });
434
+ }, CONNECTION_REFRESH_INTERVAL_MS);
435
+ return () => window.clearInterval(timer);
436
+ }, [refresh]);
437
+ const companionByBrowser = useMemo(() => {
438
+ const map = new Map();
439
+ for (const companion of companions) {
440
+ if (!map.has(companion.browser)) {
441
+ map.set(companion.browser, companion);
442
+ }
443
+ }
444
+ return map;
445
+ }, [companions]);
446
+ const pairingPayloads = useMemo(() => {
447
+ const payloads = {};
448
+ for (const browser of ["chrome", "safari"]) {
449
+ const pairing = pairings[browser];
450
+ if (pairing) {
451
+ payloads[browser] = JSON.stringify(pairingPayload(pairing), null, 2);
452
+ }
453
+ }
454
+ return payloads;
455
+ }, [pairings]);
456
+ const connectedCompanions = useMemo(() => companions.filter((companion) => companion.connectionState === "connected"), [companions]);
457
+ const primaryCompanion = connectedCompanions[0] ?? companions[0] ?? null;
458
+ const connectionSummary = useMemo(() => {
459
+ const iosRuntime = isIosRuntime();
460
+ const trackingEnabled = draft ? draft.trackingMode !== "off" : false;
461
+ const paused = draft
462
+ ? isFutureLocalDateTimeValue(draft.pauseUntilLocal)
463
+ : false;
464
+ const browserReady = Boolean(draft?.enabled) &&
465
+ trackingEnabled &&
466
+ connectedCompanions.length > 0;
467
+ const controlEnabled = Boolean(draft?.allowBrowserControl);
468
+ if (!draft) {
469
+ return {
470
+ badge: "Loading",
471
+ badgeVariant: "outline",
472
+ title: "Loading browser connection",
473
+ detail: "Checking whether Your Browser is connected to LifeOps.",
474
+ steps: [],
475
+ };
476
+ }
477
+ if (paused) {
478
+ return {
479
+ badge: "Paused",
480
+ badgeVariant: "outline",
481
+ title: "Browser access is paused",
482
+ detail: "LifeOps is paired to browsers, but tracking is paused right now, so owner-side connectors cannot see live tabs.",
483
+ steps: [
484
+ "Clear Pause until or wait for it to expire.",
485
+ "Keep Tracking on if you want connector status to stay current.",
486
+ ],
487
+ };
488
+ }
489
+ if (browserReady && controlEnabled) {
490
+ return {
491
+ badge: "Connected",
492
+ badgeVariant: "default",
493
+ title: "Your Browser is connected",
494
+ detail: connectedCompanions.length === 1
495
+ ? "LifeOps can read and control the connected browser profile."
496
+ : `LifeOps can use ${connectedCompanions.length} connected browser profiles.`,
497
+ steps: [
498
+ "Open Discord, Gmail, or any owner-side app in the connected browser profile.",
499
+ "Use connector cards below to verify that LifeOps can see the page you expect.",
500
+ ],
501
+ };
502
+ }
503
+ if (browserReady && !controlEnabled) {
504
+ return {
505
+ badge: "Attention",
506
+ badgeVariant: "secondary",
507
+ title: "Your Browser is connected, but control is off",
508
+ detail: "LifeOps can read the browser state, but it cannot open Discord, switch tabs, or navigate for you until Browser control is enabled.",
509
+ steps: [
510
+ "Turn on Browser control if you want LifeOps to open or focus sites for you.",
511
+ "Leave Browser control off only if you are okay opening the target tabs yourself.",
512
+ ],
513
+ };
514
+ }
515
+ if (!draft.enabled || !trackingEnabled) {
516
+ return {
517
+ badge: "Off",
518
+ badgeVariant: "outline",
519
+ title: "Browser access is turned off",
520
+ detail: "LifeOps is not currently tracking Your Browser, so extension pairing alone is not enough.",
521
+ steps: [
522
+ "Turn on Enabled and set Tracking to Current tab or Active tabs.",
523
+ "Then open the extension popup in the browser profile you want LifeOps to use.",
524
+ ],
525
+ };
526
+ }
527
+ if (companions.length === 0) {
528
+ return {
529
+ badge: "Setup",
530
+ badgeVariant: "secondary",
531
+ title: "No browser is connected yet",
532
+ detail: iosRuntime
533
+ ? "Connect a Chrome or Safari companion running on your Mac or cloud browser host. The iPhone app talks to that host; iOS WebKit does not expose real browser-tab automation."
534
+ : "Install the extension in the exact browser profile where you are logged into your real accounts, then open the popup once to auto-connect.",
535
+ steps: iosRuntime
536
+ ? [
537
+ "Make sure this iPhone is connected to the remote Mac or cloud backend that owns the browser companion.",
538
+ "Install and pair the Chrome or Safari companion on that host.",
539
+ "Open the extension popup there once so it can auto-connect.",
540
+ ]
541
+ : [
542
+ "Install Chrome or Safari extension from the card on the right.",
543
+ "Open LifeOps in that same browser profile.",
544
+ "Open the extension popup once so it can auto-connect.",
545
+ ],
546
+ };
547
+ }
548
+ return {
549
+ badge: "Waiting",
550
+ badgeVariant: "secondary",
551
+ title: "A browser was paired before, but it is not connected right now",
552
+ detail: "Reopen the extension popup in the correct browser profile and let it sync again.",
553
+ steps: [
554
+ "Make sure the popup points at the live LifeOps app origin.",
555
+ "Use the same browser profile that contains your logged-in accounts.",
556
+ ],
557
+ };
558
+ }, [companions.length, connectedCompanions.length, draft]);
559
+ const connectionTone = connectionSummary.badgeVariant === "default"
560
+ ? "ok"
561
+ : connectionSummary.badgeVariant === "secondary"
562
+ ? "warning"
563
+ : "muted";
564
+ const updateDraft = (key, value) => {
565
+ setDraft((current) => (current ? { ...current, [key]: value } : current));
566
+ setDraftDirty(true);
567
+ };
568
+ const saveSettings = async () => {
569
+ if (!draft) {
570
+ return;
571
+ }
572
+ setSavingSettings(true);
573
+ setError(null);
574
+ try {
575
+ const response = await client.updateBrowserBridgeSettings(settingsRequestFromDraft(draft));
576
+ setDraft(settingsToDraft(response.settings));
577
+ setDraftDirty(false);
578
+ setStatusMessage("Saved Agent Browser Bridge settings.");
579
+ }
580
+ catch (cause) {
581
+ setError(cause instanceof Error ? cause.message : String(cause));
582
+ }
583
+ finally {
584
+ setSavingSettings(false);
585
+ }
586
+ };
587
+ const enableRecommendedBrowserSettings = async () => {
588
+ if (!draft) {
589
+ return;
590
+ }
591
+ setSavingSettings(true);
592
+ setError(null);
593
+ try {
594
+ const nextDraft = {
595
+ ...draft,
596
+ enabled: true,
597
+ trackingMode: draft.trackingMode === "off" ? "current_tab" : draft.trackingMode,
598
+ allowBrowserControl: true,
599
+ requireConfirmationForAccountAffecting: true,
600
+ pauseUntilLocal: "",
601
+ };
602
+ const response = await client.updateBrowserBridgeSettings(settingsRequestFromDraft(nextDraft));
603
+ setDraft(settingsToDraft(response.settings));
604
+ setDraftDirty(false);
605
+ setStatusMessage("Browser access is enabled. Next, install the extension in the profile that has your real accounts.");
606
+ await refresh();
607
+ }
608
+ catch (cause) {
609
+ setError(cause instanceof Error ? cause.message : String(cause));
610
+ throw cause;
611
+ }
612
+ finally {
613
+ setSavingSettings(false);
614
+ }
615
+ };
616
+ const buildPackage = async (browser, options) => {
617
+ setBuildingBrowser(browser);
618
+ setError(null);
619
+ if (!options?.silent) {
620
+ setStatusMessage(`Building ${browser === "chrome" ? "Chrome" : "Safari"} companion…`);
621
+ }
622
+ try {
623
+ const response = await client.buildBrowserBridgeCompanionPackage(browser);
624
+ const nextStatus = mergePackageStatus(packageStatus, response.status);
625
+ setPackageStatus(nextStatus);
626
+ if (!options?.silent) {
627
+ setStatusMessage(`Built ${browser === "chrome" ? "Chrome" : "Safari"} companion package.`);
628
+ }
629
+ return nextStatus;
630
+ }
631
+ catch (cause) {
632
+ setError(cause instanceof Error ? cause.message : String(cause));
633
+ throw cause;
634
+ }
635
+ finally {
636
+ setBuildingBrowser(null);
637
+ }
638
+ };
639
+ const createPairing = async (browser, options) => {
640
+ setPairingBrowser(browser);
641
+ setError(null);
642
+ try {
643
+ const response = await client.createBrowserBridgeCompanionPairing(normalizePairingRequest(browser, companionByBrowser.get(browser) ?? null));
644
+ setPairings((current) => ({
645
+ ...current,
646
+ [browser]: response,
647
+ }));
648
+ if (!options?.silent) {
649
+ setStatusMessage(`Created a manual ${browser} pairing payload. Use it only if the extension cannot auto-pair itself.`);
650
+ }
651
+ await refresh();
652
+ return response;
653
+ }
654
+ catch (cause) {
655
+ setError(cause instanceof Error ? cause.message : String(cause));
656
+ throw cause;
657
+ }
658
+ finally {
659
+ setPairingBrowser(null);
660
+ }
661
+ };
662
+ const copyPairing = async (browser) => {
663
+ try {
664
+ const payload = pairingPayloads[browser];
665
+ if (!payload) {
666
+ return;
667
+ }
668
+ await copyTextToClipboard(payload);
669
+ setStatusMessage(`Copied manual ${browser} pairing JSON to the clipboard.`);
670
+ setError(null);
671
+ }
672
+ catch (cause) {
673
+ setError(cause instanceof Error ? cause.message : String(cause));
674
+ }
675
+ };
676
+ const downloadPackage = async (browser, options) => {
677
+ try {
678
+ setError(null);
679
+ const download = await client.downloadBrowserBridgeCompanionPackage(browser);
680
+ const objectUrl = URL.createObjectURL(download.blob);
681
+ const anchor = document.createElement("a");
682
+ anchor.href = objectUrl;
683
+ anchor.download = download.filename;
684
+ anchor.rel = "noopener";
685
+ document.body.appendChild(anchor);
686
+ anchor.click();
687
+ anchor.remove();
688
+ window.setTimeout(() => {
689
+ URL.revokeObjectURL(objectUrl);
690
+ }, 0);
691
+ if (!options?.silent) {
692
+ setStatusMessage(`Downloaded ${browser === "chrome" ? "Chrome" : "Safari"} companion package.`);
693
+ }
694
+ }
695
+ catch (cause) {
696
+ setError(cause instanceof Error ? cause.message : String(cause));
697
+ throw cause;
698
+ }
699
+ };
700
+ const resolvePackageTargetPath = useCallback((target) => {
701
+ switch (target) {
702
+ case "extension_root":
703
+ return packageStatus?.extensionPath ?? null;
704
+ case "chrome_build":
705
+ return packageStatus?.chromeBuildPath ?? null;
706
+ case "chrome_package":
707
+ return packageStatus?.chromePackagePath ?? null;
708
+ case "safari_web_extension":
709
+ return packageStatus?.safariWebExtensionPath ?? null;
710
+ case "safari_app":
711
+ return packageStatus?.safariAppPath ?? null;
712
+ case "safari_package":
713
+ return packageStatus?.safariPackagePath ?? null;
714
+ default:
715
+ return null;
716
+ }
717
+ }, [packageStatus]);
718
+ const openPackageTarget = async (target, revealOnly = false, options) => {
719
+ try {
720
+ const knownPath = resolvePackageTargetPath(target);
721
+ if (isElectrobunRuntime()) {
722
+ if (!knownPath) {
723
+ throw new Error("The requested extension path is not available yet");
724
+ }
725
+ await openDesktopPath(knownPath, revealOnly);
726
+ if (!options?.silent) {
727
+ setStatusMessage(revealOnly
728
+ ? "Revealed the local Agent Browser Bridge path."
729
+ : "Opened the local Agent Browser Bridge path.");
730
+ }
731
+ setError(null);
732
+ return { path: knownPath, opened: true };
733
+ }
734
+ const response = await client.openBrowserBridgeCompanionPackagePath({
735
+ target,
736
+ revealOnly,
737
+ });
738
+ if (!options?.silent) {
739
+ setStatusMessage(revealOnly
740
+ ? "Revealed the local Agent Browser Bridge path."
741
+ : "Opened the local Agent Browser Bridge path.");
742
+ }
743
+ setError(null);
744
+ return { path: response.path, opened: true };
745
+ }
746
+ catch (cause) {
747
+ const fallbackPath = resolvePackageTargetPath(target);
748
+ if (fallbackPath) {
749
+ await copyTextToClipboard(fallbackPath);
750
+ if (!options?.silent) {
751
+ setStatusMessage("Copied the local Agent Browser Bridge path to the clipboard.");
752
+ }
753
+ setError(null);
754
+ return { path: fallbackPath, opened: false };
755
+ }
756
+ setError(cause instanceof Error ? cause.message : String(cause));
757
+ throw cause;
758
+ }
759
+ };
760
+ const openBrowserManager = async (browser, options) => {
761
+ if (browser === "safari") {
762
+ if (!options?.silent) {
763
+ setStatusMessage("Safari extension permissions live in Safari > Settings > Extensions. Open the Agent Browser Bridge app once, enable the extension there, then open its popup.");
764
+ }
765
+ setError(null);
766
+ return false;
767
+ }
768
+ try {
769
+ if (browser === "chrome" &&
770
+ currentBrowser === "chrome" &&
771
+ !isElectrobunRuntime()) {
772
+ navigatePreOpenedWindow(preOpenWindow(), CHROME_EXTENSIONS_URL);
773
+ if (!options?.silent) {
774
+ setStatusMessage("Opened chrome://extensions/ in this browser profile.");
775
+ }
776
+ setError(null);
777
+ return true;
778
+ }
779
+ await client.openBrowserBridgeCompanionManager(browser);
780
+ if (!options?.silent) {
781
+ setStatusMessage(browser === "chrome"
782
+ ? "Asked Chrome to open chrome://extensions."
783
+ : "Opened the browser manager.");
784
+ }
785
+ setError(null);
786
+ return true;
787
+ }
788
+ catch (cause) {
789
+ if (browser === "chrome") {
790
+ await copyTextToClipboard(CHROME_EXTENSIONS_URL);
791
+ if (!options?.silent) {
792
+ setStatusMessage("Copied chrome://extensions/ to the clipboard.");
793
+ }
794
+ setError(null);
795
+ return false;
796
+ }
797
+ setError(cause instanceof Error ? cause.message : String(cause));
798
+ throw cause;
799
+ }
800
+ };
801
+ const installCompanion = async (browser) => {
802
+ setInstallingBrowser(browser);
803
+ setError(null);
804
+ setStatusMessage(`Preparing ${browser === "chrome" ? "Chrome" : "Safari"} install…`);
805
+ try {
806
+ const releaseTarget = releaseTargetForBrowser(browser, packageStatus?.releaseManifest);
807
+ const preOpenedChromeManager = browser === "chrome" &&
808
+ currentBrowser === "chrome" &&
809
+ !isElectrobunRuntime()
810
+ ? preOpenWindow()
811
+ : null;
812
+ const needsBuild = browser === "chrome"
813
+ ? !packageStatus?.chromeBuildPath
814
+ : isElectrobunRuntime()
815
+ ? !packageStatus?.safariAppPath
816
+ : !packageStatus?.safariPackagePath;
817
+ const hasLocalWorkspace = Boolean(packageStatus?.extensionPath);
818
+ const nextStatus = hasLocalWorkspace && needsBuild
819
+ ? await buildPackage(browser, { silent: true })
820
+ : packageStatus;
821
+ if (hasLocalWorkspace) {
822
+ if (browser === "chrome") {
823
+ if (!nextStatus?.chromeBuildPath) {
824
+ throw new Error("Chrome build folder is not available");
825
+ }
826
+ const folderResult = await openPackageTarget("chrome_build", true, {
827
+ silent: true,
828
+ });
829
+ let managerOpened;
830
+ if (preOpenedChromeManager) {
831
+ navigatePreOpenedWindow(preOpenedChromeManager, CHROME_EXTENSIONS_URL);
832
+ managerOpened = true;
833
+ }
834
+ else {
835
+ managerOpened = await openBrowserManager("chrome", {
836
+ silent: true,
837
+ });
838
+ }
839
+ setStatusMessage(managerOpened
840
+ ? folderResult.opened
841
+ ? currentBrowser === "chrome"
842
+ ? "Chrome install is prepared in this browser profile. We revealed the built LifeOps extension folder and opened chrome://extensions here. Click Load unpacked, choose that folder, then open the popup once to auto-pair."
843
+ : "Chrome install is prepared. We revealed the built LifeOps extension folder and asked Chrome to open its extensions page. Click Load unpacked and choose that folder, then open the popup once to auto-pair."
844
+ : currentBrowser === "chrome"
845
+ ? "Chrome install is prepared in this browser profile. We opened chrome://extensions here and copied the build folder path. Click Load unpacked, choose that folder, then open the popup once to auto-pair."
846
+ : "Chrome install is prepared. We asked Chrome to open its extensions page and copied the build folder path. Click Load unpacked, choose that folder, then open the popup once to auto-pair."
847
+ : folderResult.opened
848
+ ? "Chrome build folder is ready. In Chrome, open chrome://extensions, click Load unpacked, and choose the revealed LifeOps extension folder."
849
+ : "Chrome install still needs one manual step. We copied both the build folder path and chrome://extensions/, so you can load the unpacked LifeOps extension manually.");
850
+ return;
851
+ }
852
+ if (nextStatus?.safariAppPath) {
853
+ await openPackageTarget("safari_app", false, { silent: true });
854
+ setStatusMessage("Safari install is prepared. We opened the Agent Browser Bridge app bundle. Run it once, enable the Safari extension, then open the popup once to auto-pair.");
855
+ return;
856
+ }
857
+ if (nextStatus?.safariPackagePath) {
858
+ await openPackageTarget("safari_package", true, { silent: true });
859
+ setStatusMessage("Safari install is prepared. We revealed the packaged Agent Browser Bridge Safari build. Install it, enable the Safari extension, then open the popup once to auto-pair.");
860
+ return;
861
+ }
862
+ }
863
+ if (releaseTarget?.installUrl) {
864
+ await openExternalUrl(releaseTarget.installUrl);
865
+ setStatusMessage(releaseTarget.installKind === "chrome_web_store"
866
+ ? "Chrome install is prepared. We opened the Chrome Web Store listing. After install, open the extension popup in the same browser profile and it should auto-pair itself."
867
+ : releaseTarget.installKind === "apple_app_store"
868
+ ? "Safari install is prepared. We opened the App Store listing. Install the app, enable the Safari extension, then open its popup once so it can auto-pair."
869
+ : `${browser === "chrome" ? "Chrome" : "Safari"} install is prepared. We opened the release download. After install, open the extension popup in the same browser profile and it should auto-pair itself.`);
870
+ return;
871
+ }
872
+ await downloadPackage(browser, { silent: true });
873
+ setStatusMessage(`${browser === "chrome" ? "Chrome" : "Safari"} package downloaded. Install it manually, then open the extension popup once so it can auto-pair.`);
874
+ }
875
+ catch (cause) {
876
+ setError(cause instanceof Error ? cause.message : String(cause));
877
+ }
878
+ finally {
879
+ setInstallingBrowser(null);
880
+ }
881
+ };
882
+ const openDesktopBrowser = async () => {
883
+ try {
884
+ await client.openBrowserWorkspaceTab({
885
+ url: "about:blank",
886
+ title: "Browser",
887
+ show: true,
888
+ });
889
+ setTab("browser");
890
+ setActionNotice("Opened Milady Desktop Browser.", "success", 3000);
891
+ setError(null);
892
+ }
893
+ catch (cause) {
894
+ setError(cause instanceof Error ? cause.message : String(cause));
895
+ }
896
+ };
897
+ const recommendedBrowser = recommendedBrowserKind(currentBrowser);
898
+ const recommendedBrowserName = browserLabel(recommendedBrowser);
899
+ const recommendedCompanion = companionByBrowser.get(recommendedBrowser) ?? primaryCompanion;
900
+ const recommendedConnected = recommendedCompanion?.connectionState === "connected";
901
+ const recommendedArtifactReady = hasBrowserArtifact(recommendedBrowser, packageStatus);
902
+ const settingsReady = browserSettingsReady(draft);
903
+ const browserPermissionReady = companionPermissionReady(recommendedConnected ? recommendedCompanion : primaryCompanion);
904
+ const setupBusy = loading ||
905
+ savingSettings ||
906
+ buildingBrowser !== null ||
907
+ pairingBrowser !== null ||
908
+ installingBrowser !== null;
909
+ const setupSteps = useMemo(() => {
910
+ const hasAnyCompanion = companions.length > 0;
911
+ return [
912
+ {
913
+ id: "settings",
914
+ title: "Enable safe browser access",
915
+ detail: "LifeOps turns on visibility, keeps account-changing confirmations on, and clears any pause.",
916
+ status: settingsReady ? "done" : "current",
917
+ },
918
+ {
919
+ id: "install",
920
+ title: `Install ${recommendedBrowserName} companion`,
921
+ detail: currentBrowser
922
+ ? `Best path: install into this ${recommendedBrowserName} profile so pairing can happen automatically.`
923
+ : `Best path: install Chrome first, then open this setup page there before loading the extension.`,
924
+ status: !settingsReady
925
+ ? "pending"
926
+ : hasAnyCompanion
927
+ ? "done"
928
+ : recommendedArtifactReady
929
+ ? "current"
930
+ : "current",
931
+ },
932
+ {
933
+ id: "pair",
934
+ title: "Auto-connect the profile",
935
+ detail: "After install, keep this LifeOps setup page open and open the extension popup once.",
936
+ status: !hasAnyCompanion
937
+ ? "pending"
938
+ : recommendedConnected
939
+ ? "done"
940
+ : "current",
941
+ },
942
+ {
943
+ id: "permissions",
944
+ title: "Verify extension permissions",
945
+ detail: "Tabs, activeTab, DOM scripting, and all-sites access should be available for reliable connector automation.",
946
+ status: recommendedConnected
947
+ ? browserPermissionReady
948
+ ? "done"
949
+ : "attention"
950
+ : "pending",
951
+ },
952
+ ];
953
+ }, [
954
+ browserPermissionReady,
955
+ companions.length,
956
+ currentBrowser,
957
+ recommendedArtifactReady,
958
+ recommendedBrowserName,
959
+ recommendedConnected,
960
+ settingsReady,
961
+ ]);
962
+ const nextSetupStep = setupSteps.find((step) => step.status === "current") ??
963
+ setupSteps.find((step) => step.status === "attention") ??
964
+ null;
965
+ const setupComplete = setupSteps.every((step) => step.status === "done");
966
+ const primarySetupLabel = !draft
967
+ ? "Checking Setup"
968
+ : !settingsReady
969
+ ? "Enable Browser Access"
970
+ : connectedCompanions.length === 0
971
+ ? recommendedArtifactReady
972
+ ? `Continue: Open ${recommendedBrowserName} Install`
973
+ : `Continue: Build & Install in ${recommendedBrowserName}`
974
+ : recommendedConnected
975
+ ? browserPermissionReady
976
+ ? "Refresh Browser Status"
977
+ : `Review ${recommendedBrowserName} Permissions`
978
+ : `Reconnect ${recommendedBrowserName}`;
979
+ const continueBrowserSetup = async () => {
980
+ if (!draft || setupBusy) {
981
+ return;
982
+ }
983
+ try {
984
+ if (!settingsReady) {
985
+ await enableRecommendedBrowserSettings();
986
+ return;
987
+ }
988
+ if (connectedCompanions.length === 0) {
989
+ await installCompanion(recommendedBrowser);
990
+ return;
991
+ }
992
+ if (!recommendedConnected) {
993
+ const openedManager = await openBrowserManager(recommendedBrowser, {
994
+ silent: true,
995
+ });
996
+ setStatusMessage(openedManager
997
+ ? `Opened ${recommendedBrowserName} extension settings. Enable Agent Browser Bridge if needed, then open its popup once to reconnect.`
998
+ : `${recommendedBrowserName} needs a quick manual check. Enable Agent Browser Bridge in the browser's extension settings, then open its popup once to reconnect.`);
999
+ return;
1000
+ }
1001
+ if (!browserPermissionReady) {
1002
+ const openedManager = await openBrowserManager(recommendedBrowser, {
1003
+ silent: true,
1004
+ });
1005
+ setStatusMessage(openedManager
1006
+ ? `${recommendedBrowserName} is connected, but extension permissions need a check. In the extension details, allow site access for all sites and enable incognito only if you want LifeOps to see private windows.`
1007
+ : `${recommendedBrowserName} is connected, but extension permissions need a check. In Safari, use Safari > Settings > Extensions, enable Agent Browser Bridge, and review website access there.`);
1008
+ return;
1009
+ }
1010
+ await refresh({ preserveDraft: true });
1011
+ setStatusMessage("Browser setup looks healthy.");
1012
+ }
1013
+ catch (cause) {
1014
+ setError(cause instanceof Error ? cause.message : String(cause));
1015
+ }
1016
+ };
1017
+ const openSetupPage = async () => {
1018
+ const setupUrl = buildSetupUrl();
1019
+ if (!setupUrl) {
1020
+ return;
1021
+ }
1022
+ try {
1023
+ await openExternalUrl(setupUrl);
1024
+ setStatusMessage(`Opened this LifeOps setup page in your default browser. Use the ${recommendedBrowserName} profile that contains your real accounts.`);
1025
+ setError(null);
1026
+ }
1027
+ catch {
1028
+ await copyTextToClipboard(setupUrl);
1029
+ setStatusMessage("Copied this LifeOps setup page URL. Open it in the browser profile that contains your real accounts.");
1030
+ setError(null);
1031
+ }
1032
+ };
1033
+ return (_jsxs("div", { id: "lifeops-browser-setup", className: "space-y-4", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsxs("div", { className: "flex items-center gap-2 text-muted", children: [_jsx(ShieldCheck, { className: "h-4 w-4", "aria-hidden": true }), _jsx("div", { className: "text-sm font-semibold text-txt", children: "Your Browser" }), _jsx(BridgeDot, { label: connectionSummary.badge, tone: connectionTone })] }), _jsx("div", { className: "flex items-center gap-2", children: _jsx(Button, { size: "sm", variant: "outline", className: "h-8 w-8 rounded-xl p-0", disabled: loading, onClick: () => void refresh({ preserveDraft: true }), title: "Refresh", "aria-label": "Refresh", children: _jsx(RefreshCw, { className: "h-3.5 w-3.5", "aria-hidden": true }) }) })] }), statusMessage ? (_jsx("div", { className: "rounded-2xl bg-card/22 px-3 py-2 text-xs text-txt", children: statusMessage })) : null, error ? (_jsx("div", { className: "rounded-2xl bg-danger/10 px-3 py-1.5 text-xs text-danger", children: error })) : null, _jsxs("div", { className: "rounded-3xl border border-border/18 bg-[radial-gradient(circle_at_top_left,color-mix(in_srgb,var(--card)_82%,transparent),transparent_34%),linear-gradient(135deg,color-mix(in_srgb,var(--bg)_96%,transparent),color-mix(in_srgb,var(--card)_86%,transparent))] px-5 py-4 shadow-[inset_0_1px_0_rgba(255,255,255,0.07)]", children: [_jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("div", { className: "text-sm font-semibold text-txt", children: "Guided Browser Setup" }), _jsx("div", { className: "max-w-2xl text-xs leading-relaxed text-muted", children: "Use this when you want the easy path. LifeOps will enable the recommended browser settings, build or open the companion installer, and take you to the right browser page for the current profile." })] }), _jsx(Badge, { variant: setupComplete ? "default" : "secondary", children: setupComplete
1034
+ ? "Ready"
1035
+ : nextSetupStep
1036
+ ? nextSetupStep.title
1037
+ : "Checking" })] }), _jsx("div", { className: "mt-4 grid gap-2 md:grid-cols-2", children: setupSteps.map((step) => {
1038
+ const done = step.status === "done";
1039
+ const active = step.status === "current" || step.status === "attention";
1040
+ return (_jsxs("div", { className: `rounded-2xl border px-3 py-3 text-xs ${done
1041
+ ? "border-emerald-500/18 bg-emerald-500/10"
1042
+ : active
1043
+ ? "border-amber-500/24 bg-amber-500/10"
1044
+ : "border-border/14 bg-card/12"}`, children: [_jsxs("div", { className: "flex items-center gap-2", children: [done ? (_jsx(CheckCircle2, { className: "h-3.5 w-3.5 text-emerald-400" })) : (_jsx(Circle, { className: `h-3.5 w-3.5 ${active ? "text-amber-300" : "text-muted"}` })), _jsx("span", { className: "font-semibold text-txt", children: step.title }), _jsx("span", { className: "ml-auto rounded-full border border-border/18 px-2 py-0.5 text-[10px] uppercase tracking-wide text-muted", children: statusLabel(step.status) })] }), _jsx("div", { className: "mt-1.5 leading-relaxed text-muted", children: step.detail })] }, step.id));
1045
+ }) }), _jsxs("div", { className: "mt-4 flex flex-wrap gap-2", children: [_jsxs(Button, { size: "sm", className: "h-8 rounded-xl px-3 text-xs font-semibold", disabled: setupBusy || !draft, onClick: () => void continueBrowserSetup(), children: [_jsx(Sparkles, { className: "mr-1.5 h-3 w-3" }), setupBusy ? "Working..." : primarySetupLabel] }), _jsxs(Button, { size: "sm", variant: "outline", className: "h-8 rounded-xl px-3 text-xs font-semibold", onClick: () => void openSetupPage(), children: [_jsx(ExternalLink, { className: "mr-1.5 h-3 w-3" }), "Open This Setup Page"] }), currentBrowser === "chrome" ? (_jsx(Button, { size: "sm", variant: "outline", className: "h-8 rounded-xl px-3 text-xs font-semibold", disabled: setupBusy, onClick: () => void openBrowserManager("chrome"), children: "Open Chrome Extensions" })) : null] })] }), _jsxs("details", { className: "rounded-2xl border border-border/18 bg-card/12 px-4 py-3", children: [_jsxs("summary", { className: "flex cursor-pointer list-none items-center justify-between gap-3 text-sm font-semibold text-txt", children: [_jsx("span", { children: "Browser profiles" }), _jsx(BridgeMeter, { connected: connectedCompanions.length, total: companions.length })] }), _jsxs("div", { className: "mt-4 grid gap-5 lg:grid-cols-[minmax(0,0.95fr)_minmax(0,1.05fr)]", children: [_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "rounded-3xl border border-border/18 bg-[linear-gradient(180deg,color-mix(in_srgb,var(--card)_94%,transparent),color-mix(in_srgb,var(--bg)_98%,transparent))] px-5 py-4 shadow-[inset_0_1px_0_rgba(255,255,255,0.06)]", children: [_jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("div", { className: "text-sm font-semibold text-txt", children: connectionSummary.title }), _jsx("div", { className: "max-w-xl text-xs leading-relaxed text-muted", children: connectionSummary.detail })] }), _jsx(Badge, { variant: connectionSummary.badgeVariant, children: connectionSummary.badge })] }), connectionSummary.steps.length > 0 ? (_jsx("div", { className: "mt-4 grid gap-2", children: connectionSummary.steps.map((step) => (_jsx("div", { className: "rounded-2xl bg-card/20 px-3 py-2 text-xs text-muted", children: step }, step))) })) : null, primaryCompanion ? (_jsxs("div", { className: "mt-4 rounded-2xl bg-card/20 px-3 py-2 text-xs text-muted", children: ["Primary browser:", " ", _jsxs("span", { className: "font-semibold text-txt", children: [primaryCompanion.browser === "safari"
1046
+ ? "Safari"
1047
+ : "Chrome", " ", "/ ", primaryCompanion.profileLabel] }), " • ", permissionSummary(primaryCompanion.permissions)] })) : null, isElectrobunRuntime() ? (_jsx("div", { className: "mt-4", children: _jsxs(Button, { size: "sm", variant: "outline", className: "h-8 rounded-xl px-3 text-xs font-semibold", onClick: () => void openDesktopBrowser(), children: [_jsx(Monitor, { className: "mr-1.5 h-3 w-3" }), "Open Milady Desktop Browser"] }) })) : null] }), _jsxs("div", { className: "space-y-2", children: [_jsx("div", { className: "text-sm font-semibold text-txt", children: "Connected Browsers" }), companions.length > 0 ? (_jsx("div", { className: "grid gap-2", children: companions.map((companion) => (_jsxs("div", { className: "rounded-2xl bg-card/16 px-3 py-3 text-xs", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsxs(Badge, { variant: "outline", className: "text-2xs", children: [companion.browser, "/", companion.profileLabel] }), _jsx(Badge, { variant: "secondary", className: "text-2xs", children: companion.connectionState }), _jsx("span", { className: "text-muted", children: formatTimestamp(companion.lastSeenAt) ??
1048
+ "Never seen" })] }), _jsx("div", { className: "mt-1 text-muted", children: permissionSummary(companion.permissions) })] }, companion.id))) })) : (_jsx("div", { className: "rounded-2xl bg-card/14 px-3 py-3 text-xs text-muted", children: "No browser profiles have connected yet. After installing the extension, open its popup once in the browser profile you want LifeOps to use." }))] })] }), _jsxs("div", { className: "space-y-3", children: [_jsx("div", { className: "text-sm font-semibold text-txt", children: "Connect a Browser" }), _jsx(BrowserCompanionRow, { currentBrowser: currentBrowser, browser: "chrome", buildPath: packageStatus?.chromeBuildPath, packagePath: packageStatus?.chromePackagePath, localWorkspaceAvailable: Boolean(packageStatus?.extensionPath), releaseManifest: packageStatus?.releaseManifest ?? null, busy: buildingBrowser === "chrome" ||
1049
+ pairingBrowser === "chrome" ||
1050
+ installingBrowser === "chrome", pairing: pairings.chrome ?? null, onInstall: installCompanion, onBuild: buildPackage, onCreatePairing: createPairing, onCopyPairing: copyPairing, onDownload: downloadPackage, onOpenTarget: openPackageTarget, onOpenManager: openBrowserManager }), _jsx(BrowserCompanionRow, { currentBrowser: currentBrowser, browser: "safari", buildPath: packageStatus?.safariWebExtensionPath, packagePath: packageStatus?.safariPackagePath, appPath: packageStatus?.safariAppPath, localWorkspaceAvailable: Boolean(packageStatus?.extensionPath), releaseManifest: packageStatus?.releaseManifest ?? null, busy: buildingBrowser === "safari" ||
1051
+ pairingBrowser === "safari" ||
1052
+ installingBrowser === "safari", pairing: pairings.safari ?? null, onInstall: installCompanion, onBuild: buildPackage, onCreatePairing: createPairing, onCopyPairing: copyPairing, onDownload: downloadPackage, onOpenTarget: openPackageTarget, onOpenManager: openBrowserManager }), ["chrome", "safari"].map((browser) => {
1053
+ const payload = pairingPayloads[browser];
1054
+ if (!payload) {
1055
+ return null;
1056
+ }
1057
+ return (_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("span", { className: "text-xs font-semibold text-txt", children: [browser === "chrome" ? "Chrome" : "Safari", " pairing"] }), _jsxs(Button, { size: "sm", variant: "outline", onClick: () => void copyPairing(browser), children: [_jsx(Copy, { className: "mr-1.5 h-3 w-3" }), "Copy"] })] }), _jsx(Textarea, { readOnly: true, rows: 5, value: payload, className: "font-mono text-xs" }), _jsx("div", { className: "text-[11px] text-muted", children: "Manual fallback only. Automatic pairing should work as soon as the extension popup can see this app in the same browser profile." })] }, browser));
1058
+ })] })] }), _jsxs("details", { className: "mt-4 rounded-2xl border border-border/18 bg-card/12 px-4 py-3", children: [_jsx("summary", { className: "cursor-pointer list-none text-sm font-semibold text-txt", children: "Advanced Browser Rules" }), _jsx("div", { className: "mt-4 space-y-4", children: draft ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("div", { className: "text-xs text-muted", children: "These settings control what LifeOps is allowed to see or automate in Your Browser." }), _jsx(Button, { size: "sm", variant: "outline", className: "h-8 rounded-xl px-3 text-xs font-semibold", disabled: savingSettings || loading, onClick: () => void saveSettings(), children: savingSettings ? "Saving..." : "Save" })] }), _jsxs("div", { className: "divide-y divide-border/18", children: [_jsx(BrowserSettingRow, { checked: draft.enabled, hint: "Master switch for owner-side browser visibility.", label: "Enabled", onCheckedChange: (checked) => updateDraft("enabled", checked) }), _jsx(BrowserSettingRow, { checked: draft.allowBrowserControl, hint: "Required if LifeOps should open Discord, switch tabs, or navigate for you.", label: "Browser control", onCheckedChange: (checked) => updateDraft("allowBrowserControl", checked) }), _jsx(BrowserSettingRow, { checked: draft.requireConfirmationForAccountAffecting, hint: "Ask before actions that could change accounts or submit data.", label: "Require confirmation", onCheckedChange: (checked) => updateDraft("requireConfirmationForAccountAffecting", checked) }), _jsx(BrowserSettingRow, { checked: draft.incognitoEnabled, hint: "Include incognito windows when the browser has granted that permission.", label: "Incognito", onCheckedChange: (checked) => updateDraft("incognitoEnabled", checked) })] }), _jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs text-muted", children: "Tracking" }), _jsx("div", { className: "text-[11px] text-muted", children: "Choose whether LifeOps sees only the current tab or multiple active tabs." }), _jsx(SegmentedControl, { value: draft.trackingMode, onValueChange: (mode) => updateDraft("trackingMode", mode), items: ["off", "current_tab", "active_tabs"].map((mode) => ({
1059
+ value: mode,
1060
+ label: trackingModeLabel(mode),
1061
+ })), className: "w-full max-w-full border-border/28 bg-transparent p-0.5", buttonClassName: "min-h-8 flex-1 justify-center px-2.5 py-1.5 text-xs" })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs text-muted", children: "Site access" }), _jsx("div", { className: "text-[11px] text-muted", children: "Restrict LifeOps to the current site, an allow-list, or all sites." }), _jsx(SegmentedControl, { value: draft.siteAccessMode, onValueChange: (mode) => updateDraft("siteAccessMode", mode), items: BROWSER_BRIDGE_SITE_ACCESS_MODES.map((mode) => ({
1062
+ value: mode,
1063
+ label: siteAccessModeLabel(mode),
1064
+ })), className: "w-full max-w-full border-border/28 bg-transparent p-0.5", buttonClassName: "min-h-8 flex-1 justify-center px-2.5 py-1.5 text-xs" })] })] }), _jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "browser-bridge-max-tabs", className: "text-xs text-muted", children: "Max remembered tabs" }), _jsx("div", { className: "text-[11px] text-muted", children: "Controls how much recent browser context LifeOps keeps around." }), _jsx(Input, { id: "browser-bridge-max-tabs", value: draft.maxRememberedTabs, onChange: (event) => updateDraft("maxRememberedTabs", event.currentTarget.value), inputMode: "numeric" })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "browser-bridge-pause-until", className: "text-xs text-muted", children: "Pause until" }), _jsx("div", { className: "text-[11px] text-muted", children: "Temporarily stop browser visibility without disconnecting your paired browser." }), _jsxs("div", { className: "flex flex-wrap gap-1.5 sm:flex-nowrap", children: [_jsx(Input, { id: "browser-bridge-pause-until", type: "datetime-local", value: draft.pauseUntilLocal, onChange: (event) => updateDraft("pauseUntilLocal", event.currentTarget.value), className: "min-w-0 flex-1" }), _jsx(Button, { size: "sm", variant: "outline", className: "h-9 rounded-xl px-3 text-xs font-semibold", onClick: () => updateDraft("pauseUntilLocal", formatDateTimeLocalValue(new Date(Date.now() + 60 * 60 * 1000).toISOString())), children: "1h" }), _jsx(Button, { size: "sm", variant: "outline", className: "h-9 rounded-xl px-3 text-xs font-semibold", onClick: () => updateDraft("pauseUntilLocal", ""), children: "Now" })] })] })] }), _jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "browser-bridge-granted-origins", className: "text-xs text-muted", children: "Granted origins" }), _jsx("div", { className: "text-[11px] text-muted", children: "When Site access is set to Granted sites, only these origins are readable." }), _jsx(Textarea, { id: "browser-bridge-granted-origins", rows: 3, placeholder: "https://mail.google.com", value: draft.grantedOriginsText, onChange: (event) => updateDraft("grantedOriginsText", event.currentTarget.value) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "browser-bridge-blocked-origins", className: "text-xs text-muted", children: "Blocked origins" }), _jsx("div", { className: "text-[11px] text-muted", children: "These origins are never readable, even if broader site access is enabled." }), _jsx(Textarea, { id: "browser-bridge-blocked-origins", rows: 3, placeholder: "https://bank.example.com", value: draft.blockedOriginsText, onChange: (event) => updateDraft("blockedOriginsText", event.currentTarget.value) })] })] })] })) : loading ? (_jsx("div", { className: "text-xs text-muted", children: "Loading" })) : null })] })] })] }));
1065
+ }