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

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 (377) 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/services/auth-store.d.ts +1 -1
  327. package/packages/app-core/src/services/auth-store.d.ts.map +1 -1
  328. package/packages/app-core/src/services/auth-store.js +1 -1
  329. package/packages/app-core/src/shell/AppWindowRenderer.d.ts +17 -0
  330. package/packages/app-core/src/shell/AppWindowRenderer.d.ts.map +1 -0
  331. package/packages/app-core/src/shell/AppWindowRenderer.js +337 -0
  332. package/packages/app-core/src/shell/DetachedShellRoot.js +4 -1
  333. package/packages/app-core/src/shell/index.d.ts +1 -0
  334. package/packages/app-core/src/shell/index.d.ts.map +1 -1
  335. package/packages/app-core/src/shell/index.js +1 -0
  336. package/packages/app-core/src/state/startup-coordinator.d.ts.map +1 -1
  337. package/packages/app-core/src/state/startup-coordinator.js +0 -3
  338. package/packages/app-core/src/state/startup-phase-poll.d.ts.map +1 -1
  339. package/packages/app-core/src/state/startup-phase-poll.js +2 -4
  340. package/packages/app-core/src/state/usePluginsSkillsState.d.ts +6 -6
  341. package/packages/native-plugins/mobile-signals/src/definitions.d.ts +162 -0
  342. package/packages/native-plugins/mobile-signals/src/definitions.d.ts.map +1 -0
  343. package/packages/native-plugins/mobile-signals/src/definitions.js +1 -0
  344. package/packages/native-plugins/mobile-signals/src/index.d.ts +4 -0
  345. package/packages/native-plugins/mobile-signals/src/index.d.ts.map +1 -0
  346. package/packages/native-plugins/mobile-signals/src/index.js +6 -0
  347. package/packages/native-plugins/mobile-signals/src/web.d.ts +29 -0
  348. package/packages/native-plugins/mobile-signals/src/web.d.ts.map +1 -0
  349. package/packages/native-plugins/mobile-signals/src/web.js +269 -0
  350. package/packages/shared/src/app-hero-art.d.ts.map +1 -1
  351. package/packages/shared/src/app-hero-art.js +13 -0
  352. package/packages/shared/src/contracts/lifeops.d.ts +10 -0
  353. package/packages/shared/src/contracts/lifeops.d.ts.map +1 -1
  354. package/packages/shared/src/contracts/lifeops.js +5 -0
  355. package/packages/typescript/src/features/advanced-capabilities/experience/actions/record-experience.d.ts.map +1 -1
  356. package/packages/typescript/src/features/advanced-capabilities/experience/actions/record-experience.js +46 -4
  357. package/packages/typescript/src/features/advanced-capabilities/experience/evaluators/experienceEvaluator.d.ts.map +1 -1
  358. package/packages/typescript/src/features/advanced-capabilities/experience/evaluators/experienceEvaluator.js +34 -124
  359. package/packages/typescript/src/features/advanced-capabilities/experience/service.d.ts.map +1 -1
  360. package/packages/typescript/src/features/advanced-capabilities/experience/service.js +56 -0
  361. package/packages/typescript/src/features/advanced-capabilities/experience/types.d.ts +7 -0
  362. package/packages/typescript/src/features/advanced-capabilities/experience/types.d.ts.map +1 -1
  363. package/packages/typescript/src/features/advanced-capabilities/experience/utils/experienceText.d.ts +7 -0
  364. package/packages/typescript/src/features/advanced-capabilities/experience/utils/experienceText.d.ts.map +1 -0
  365. package/packages/typescript/src/features/advanced-capabilities/experience/utils/experienceText.js +123 -0
  366. package/apps/app-training/src/ui/FineTuningView.d.ts +0 -5
  367. package/apps/app-training/src/ui/FineTuningView.d.ts.map +0 -1
  368. package/apps/app-training/src/ui/FineTuningView.js +0 -388
  369. package/apps/app-training/src/ui/fine-tuning-panels.d.ts +0 -111
  370. package/apps/app-training/src/ui/fine-tuning-panels.d.ts.map +0 -1
  371. package/apps/app-training/src/ui/fine-tuning-panels.js +0 -130
  372. package/apps/app-training/src/ui/index.d.ts +0 -3
  373. package/apps/app-training/src/ui/index.d.ts.map +0 -1
  374. package/apps/app-training/src/ui/index.js +0 -2
  375. package/packages/app-core/src/api/trusted-local-request.d.ts +0 -4
  376. package/packages/app-core/src/api/trusted-local-request.d.ts.map +0 -1
  377. package/packages/app-core/src/api/trusted-local-request.js +0 -176
@@ -0,0 +1,1041 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Badge, Button, client, Input, SegmentedControl, Textarea, useApp, } from "@elizaos/app-core";
3
+ import { useCallback, useEffect, useMemo, useState, } from "react";
4
+ import { useGoogleLifeOpsConnector } from "../hooks/useGoogleLifeOpsConnector.js";
5
+ const CONNECTOR_REFRESH_INTERVAL_MS = 30_000;
6
+ const GMAIL_MESSAGE_LIMIT = 12;
7
+ const GMAIL_BULK_MESSAGE_LIMIT = 50;
8
+ const TODAY_WINDOW_DAYS = 1;
9
+ const WEEK_WINDOW_DAYS = 7;
10
+ function capabilitySet(status) {
11
+ return new Set(status?.grantedCapabilities ?? []);
12
+ }
13
+ function sideLabel(side, t) {
14
+ return side === "owner"
15
+ ? t("lifeopsworkspace.user", {
16
+ defaultValue: "User",
17
+ })
18
+ : t("chat.agentType", {
19
+ defaultValue: "Agent",
20
+ });
21
+ }
22
+ function connectorStatusLabel(status, t) {
23
+ if (status?.connected) {
24
+ return t("lifeopsworkspace.connected", {
25
+ defaultValue: "Connected",
26
+ });
27
+ }
28
+ switch (status?.reason) {
29
+ case "needs_reauth":
30
+ return t("lifeopsworkspace.needsReauth", {
31
+ defaultValue: "Needs reauth",
32
+ });
33
+ case "config_missing":
34
+ return t("lifeopsworkspace.needsSetup", {
35
+ defaultValue: "Needs setup",
36
+ });
37
+ case "token_missing":
38
+ return t("lifeopsworkspace.tokenMissing", {
39
+ defaultValue: "Token missing",
40
+ });
41
+ default:
42
+ return t("lifeopsworkspace.notConnected", {
43
+ defaultValue: "Not connected",
44
+ });
45
+ }
46
+ }
47
+ function readIdentityLabel(identity, t) {
48
+ if (!identity) {
49
+ return {
50
+ primary: t("lifeopsworkspace.notConnected", {
51
+ defaultValue: "Not connected",
52
+ }),
53
+ secondary: null,
54
+ };
55
+ }
56
+ const name = typeof identity.name === "string" && identity.name.trim().length > 0
57
+ ? identity.name.trim()
58
+ : null;
59
+ const email = typeof identity.email === "string" && identity.email.trim().length > 0
60
+ ? identity.email.trim()
61
+ : null;
62
+ return {
63
+ primary: name ??
64
+ email ??
65
+ t("lifeopsworkspace.connected", {
66
+ defaultValue: "Connected",
67
+ }),
68
+ secondary: name && email ? email : null,
69
+ };
70
+ }
71
+ function startOfLocalDay(date = new Date()) {
72
+ const next = new Date(date);
73
+ next.setHours(0, 0, 0, 0);
74
+ return next;
75
+ }
76
+ function addDays(date, days) {
77
+ const next = new Date(date);
78
+ next.setDate(next.getDate() + days);
79
+ return next;
80
+ }
81
+ function combineDateTime(dateValue, timeValue) {
82
+ if (!dateValue || !timeValue) {
83
+ return null;
84
+ }
85
+ const parsed = new Date(`${dateValue}T${timeValue}`);
86
+ return Number.isFinite(parsed.getTime()) ? parsed.toISOString() : null;
87
+ }
88
+ function formatLocalDateTime(value, timeZone) {
89
+ if (!value) {
90
+ return "—";
91
+ }
92
+ const parsed = Date.parse(value);
93
+ if (!Number.isFinite(parsed)) {
94
+ return value;
95
+ }
96
+ return new Intl.DateTimeFormat(undefined, {
97
+ month: "short",
98
+ day: "numeric",
99
+ hour: "numeric",
100
+ minute: "2-digit",
101
+ timeZone,
102
+ }).format(new Date(parsed));
103
+ }
104
+ function formatDayLabel(value, timeZone) {
105
+ const parsed = Date.parse(value);
106
+ if (!Number.isFinite(parsed)) {
107
+ return value;
108
+ }
109
+ return new Intl.DateTimeFormat(undefined, {
110
+ weekday: "short",
111
+ month: "short",
112
+ day: "numeric",
113
+ timeZone,
114
+ }).format(new Date(parsed));
115
+ }
116
+ function formatTimeOfDay(value, timeZone) {
117
+ const parsed = Date.parse(value);
118
+ if (!Number.isFinite(parsed)) {
119
+ return value;
120
+ }
121
+ return new Intl.DateTimeFormat(undefined, {
122
+ hour: "numeric",
123
+ minute: "2-digit",
124
+ timeZone,
125
+ }).format(new Date(parsed));
126
+ }
127
+ function formatEventWindow(event, t, timeZone) {
128
+ if (event.isAllDay) {
129
+ return t("lifeopsworkspace.allDay", {
130
+ defaultValue: "All day",
131
+ });
132
+ }
133
+ return `${formatTimeOfDay(event.startAt, timeZone)} - ${formatTimeOfDay(event.endAt, timeZone)}`;
134
+ }
135
+ function eventOriginLabel(event) {
136
+ const parts = [event.calendarSummary, event.accountEmail].filter((value) => typeof value === "string" && value.trim().length > 0);
137
+ if (parts.length === 0) {
138
+ return null;
139
+ }
140
+ return parts.join(" · ");
141
+ }
142
+ function toLocalDateKey(date, timeZone) {
143
+ const formatter = new Intl.DateTimeFormat("en-CA", {
144
+ timeZone,
145
+ year: "numeric",
146
+ month: "2-digit",
147
+ day: "2-digit",
148
+ });
149
+ const parts = formatter.formatToParts(date);
150
+ const year = parts.find((part) => part.type === "year")?.value ?? "0000";
151
+ const month = parts.find((part) => part.type === "month")?.value ?? "00";
152
+ const day = parts.find((part) => part.type === "day")?.value ?? "00";
153
+ return `${year}-${month}-${day}`;
154
+ }
155
+ function groupEventsByDay(events, timeZone) {
156
+ const grouped = new Map();
157
+ for (const event of [...events].sort((left, right) => left.startAt.localeCompare(right.startAt))) {
158
+ const dayKey = toLocalDateKey(new Date(event.startAt), timeZone);
159
+ const existing = grouped.get(dayKey);
160
+ if (existing) {
161
+ existing.events.push(event);
162
+ continue;
163
+ }
164
+ grouped.set(dayKey, {
165
+ label: formatDayLabel(event.startAt, timeZone),
166
+ events: [event],
167
+ });
168
+ }
169
+ return [...grouped.entries()].map(([dayKey, value]) => ({
170
+ dayKey,
171
+ label: value.label,
172
+ events: value.events,
173
+ }));
174
+ }
175
+ function sortMessages(messages) {
176
+ return [...messages].sort((left, right) => {
177
+ if (left.likelyReplyNeeded !== right.likelyReplyNeeded) {
178
+ return left.likelyReplyNeeded ? -1 : 1;
179
+ }
180
+ return right.receivedAt.localeCompare(left.receivedAt);
181
+ });
182
+ }
183
+ function parseGmailLabelIds(value) {
184
+ return value
185
+ .split(",")
186
+ .map((labelId) => labelId.trim())
187
+ .filter((labelId) => labelId.length > 0);
188
+ }
189
+ function isDestructiveGmailOperation(operation) {
190
+ return (operation === "trash" ||
191
+ operation === "delete" ||
192
+ operation === "report_spam");
193
+ }
194
+ function gmailOperationLabel(operation, t) {
195
+ switch (operation) {
196
+ case "archive":
197
+ return t("lifeopsworkspace.archive", { defaultValue: "Archive" });
198
+ case "trash":
199
+ return t("lifeopsworkspace.trash", { defaultValue: "Trash" });
200
+ case "report_spam":
201
+ return t("lifeopsworkspace.reportSpam", {
202
+ defaultValue: "Report spam",
203
+ });
204
+ case "mark_read":
205
+ return t("lifeopsworkspace.markRead", { defaultValue: "Mark read" });
206
+ case "mark_unread":
207
+ return t("lifeopsworkspace.markUnread", {
208
+ defaultValue: "Mark unread",
209
+ });
210
+ case "apply_label":
211
+ return t("lifeopsworkspace.applyLabel", {
212
+ defaultValue: "Apply label",
213
+ });
214
+ case "remove_label":
215
+ return t("lifeopsworkspace.removeLabel", {
216
+ defaultValue: "Remove label",
217
+ });
218
+ case "delete":
219
+ return t("lifeopsworkspace.delete", { defaultValue: "Delete" });
220
+ }
221
+ }
222
+ function useLifeOpsSideWorkspace({ side, calendarWindow, timeZone, }) {
223
+ const { setActionNotice, t } = useApp();
224
+ const connector = useGoogleLifeOpsConnector({
225
+ pollWhileDisconnected: false,
226
+ side,
227
+ pollIntervalMs: CONNECTOR_REFRESH_INTERVAL_MS,
228
+ });
229
+ const status = connector.status;
230
+ const capabilities = useMemo(() => capabilitySet(status), [status]);
231
+ const connected = status?.connected === true;
232
+ const calendarEnabled = connected &&
233
+ (capabilities.has("google.calendar.read") ||
234
+ capabilities.has("google.calendar.write"));
235
+ const emailEnabled = connected &&
236
+ (capabilities.has("google.gmail.triage") ||
237
+ capabilities.has("google.gmail.send"));
238
+ const emailManageEnabled = connected && capabilities.has("google.gmail.manage");
239
+ const [loading, setLoading] = useState(false);
240
+ const [error, setError] = useState(null);
241
+ const [calendarFeed, setCalendarFeed] = useState(null);
242
+ const [gmailFeed, setGmailFeed] = useState(null);
243
+ const [gmailRecommendations, setGmailRecommendations] = useState(null);
244
+ const [gmailQuery, setGmailQuery] = useState("in:inbox");
245
+ const [gmailReplyNeededOnly, setGmailReplyNeededOnly] = useState(false);
246
+ const [gmailIncludeSpamTrash, setGmailIncludeSpamTrash] = useState(false);
247
+ const [gmailSelectedMessageIds, setGmailSelectedMessageIds] = useState([]);
248
+ const [gmailLabelIds, setGmailLabelIds] = useState("");
249
+ const [gmailManageConfirmed, setGmailManageConfirmed] = useState(false);
250
+ const [selectedCalendarId, setSelectedCalendarId] = useState(null);
251
+ const [selectedMessageId, setSelectedMessageId] = useState(null);
252
+ const [draftTone, setDraftTone] = useState("neutral");
253
+ const [drafting, setDrafting] = useState(false);
254
+ const [sending, setSending] = useState(false);
255
+ const [managing, setManaging] = useState(false);
256
+ const [draft, setDraft] = useState(null);
257
+ const [draftBody, setDraftBody] = useState("");
258
+ const [sendConfirmed, setSendConfirmed] = useState(false);
259
+ const [eventTitle, setEventTitle] = useState("");
260
+ const [eventDate, setEventDate] = useState(new Date().toISOString().slice(0, 10));
261
+ const [eventTime, setEventTime] = useState("09:00");
262
+ const [eventDurationMinutes, setEventDurationMinutes] = useState("30");
263
+ const [eventLocation, setEventLocation] = useState("");
264
+ const [creatingEvent, setCreatingEvent] = useState(false);
265
+ const windowDays = calendarWindow === "week" ? WEEK_WINDOW_DAYS : TODAY_WINDOW_DAYS;
266
+ const load = useCallback(async (options) => {
267
+ if (!connected || !status) {
268
+ setLoading(false);
269
+ setError(null);
270
+ setCalendarFeed(null);
271
+ setGmailFeed(null);
272
+ setGmailRecommendations(null);
273
+ setGmailSelectedMessageIds([]);
274
+ setDraft(null);
275
+ setDraftBody("");
276
+ setSendConfirmed(false);
277
+ return;
278
+ }
279
+ setLoading(true);
280
+ setError(null);
281
+ try {
282
+ const [nextCalendarFeed, nextGmailFeed] = await Promise.all([
283
+ calendarEnabled
284
+ ? client.getLifeOpsCalendarFeed({
285
+ side: status.side,
286
+ mode: status.mode,
287
+ timeMin: startOfLocalDay().toISOString(),
288
+ timeMax: addDays(startOfLocalDay(), windowDays).toISOString(),
289
+ timeZone,
290
+ forceSync: options?.forceSync,
291
+ })
292
+ : Promise.resolve(null),
293
+ emailEnabled
294
+ ? client.getLifeOpsGmailTriage({
295
+ side: status.side,
296
+ mode: status.mode,
297
+ maxResults: GMAIL_MESSAGE_LIMIT,
298
+ forceSync: options?.forceSync,
299
+ })
300
+ : Promise.resolve(null),
301
+ ]);
302
+ setCalendarFeed(nextCalendarFeed);
303
+ setGmailFeed(nextGmailFeed);
304
+ setGmailRecommendations(null);
305
+ }
306
+ catch (cause) {
307
+ setError(cause instanceof Error && cause.message.trim().length > 0
308
+ ? cause.message.trim()
309
+ : t("lifeopsworkspace.loadFailed", {
310
+ defaultValue: "Workspace failed to load.",
311
+ }));
312
+ }
313
+ finally {
314
+ setLoading(false);
315
+ }
316
+ }, [calendarEnabled, connected, emailEnabled, status, t, timeZone, windowDays]);
317
+ useEffect(() => {
318
+ void load();
319
+ }, [load]);
320
+ const calendarEvents = useMemo(() => [...(calendarFeed?.events ?? [])].sort((left, right) => left.startAt.localeCompare(right.startAt)), [calendarFeed]);
321
+ const groupedCalendarEvents = useMemo(() => groupEventsByDay(calendarEvents, timeZone), [calendarEvents, timeZone]);
322
+ const selectedCalendarEvent = useMemo(() => calendarEvents.find((event) => event.id === selectedCalendarId) ??
323
+ calendarEvents[0] ??
324
+ null, [calendarEvents, selectedCalendarId]);
325
+ const gmailMessages = useMemo(() => sortMessages(gmailFeed?.messages ?? []), [gmailFeed]);
326
+ const selectedGmailMessage = useMemo(() => gmailMessages.find((message) => message.id === selectedMessageId) ??
327
+ gmailMessages[0] ??
328
+ null, [gmailMessages, selectedMessageId]);
329
+ const identity = useMemo(() => readIdentityLabel(status?.identity ?? null, t), [status?.identity, t]);
330
+ useEffect(() => {
331
+ if (calendarEvents.length === 0) {
332
+ setSelectedCalendarId(null);
333
+ return;
334
+ }
335
+ if (selectedCalendarId &&
336
+ calendarEvents.some((event) => event.id === selectedCalendarId)) {
337
+ return;
338
+ }
339
+ setSelectedCalendarId(calendarEvents[0].id);
340
+ }, [calendarEvents, selectedCalendarId]);
341
+ useEffect(() => {
342
+ if (gmailMessages.length === 0) {
343
+ setSelectedMessageId(null);
344
+ setGmailSelectedMessageIds([]);
345
+ setDraft(null);
346
+ setDraftBody("");
347
+ setSendConfirmed(false);
348
+ return;
349
+ }
350
+ if (selectedMessageId &&
351
+ gmailMessages.some((message) => message.id === selectedMessageId)) {
352
+ return;
353
+ }
354
+ setSelectedMessageId(gmailMessages[0].id);
355
+ setSendConfirmed(false);
356
+ }, [gmailMessages, selectedMessageId]);
357
+ useEffect(() => {
358
+ const visibleIds = new Set(gmailMessages.map((message) => message.id));
359
+ setGmailSelectedMessageIds((current) => current.filter((messageId) => visibleIds.has(messageId)));
360
+ }, [gmailMessages]);
361
+ const handleSelectGmailMessage = useCallback((messageId) => {
362
+ setSelectedMessageId(messageId);
363
+ setSendConfirmed(false);
364
+ }, []);
365
+ const refresh = useCallback(async () => {
366
+ await connector.refresh({ silent: true });
367
+ await load({ forceSync: true });
368
+ setGmailSelectedMessageIds([]);
369
+ setGmailManageConfirmed(false);
370
+ }, [connector, load]);
371
+ const handleCreateEvent = useCallback(async () => {
372
+ if (!status || !calendarEnabled) {
373
+ return;
374
+ }
375
+ const startAt = combineDateTime(eventDate, eventTime);
376
+ const durationMinutes = Number(eventDurationMinutes);
377
+ if (!eventTitle.trim() || !startAt || !Number.isFinite(durationMinutes)) {
378
+ setError(t("lifeopsworkspace.createEventValidation", {
379
+ defaultValue: "Enter a title, date, time, and duration.",
380
+ }));
381
+ return;
382
+ }
383
+ setCreatingEvent(true);
384
+ setError(null);
385
+ try {
386
+ const result = await client.createLifeOpsCalendarEvent({
387
+ side: status.side,
388
+ mode: status.mode,
389
+ title: eventTitle.trim(),
390
+ location: eventLocation.trim() || undefined,
391
+ startAt,
392
+ timeZone,
393
+ durationMinutes,
394
+ });
395
+ setActionNotice(t("lifeopsworkspace.createdEvent", {
396
+ defaultValue: "Created {{title}}",
397
+ title: result.event.title,
398
+ }), "success", 2400);
399
+ setEventTitle("");
400
+ setEventLocation("");
401
+ await refresh();
402
+ setSelectedCalendarId(result.event.id);
403
+ }
404
+ catch (cause) {
405
+ setError(cause instanceof Error && cause.message.trim().length > 0
406
+ ? cause.message.trim()
407
+ : t("lifeopsworkspace.createEventFailed", {
408
+ defaultValue: "Could not create the event.",
409
+ }));
410
+ }
411
+ finally {
412
+ setCreatingEvent(false);
413
+ }
414
+ }, [
415
+ calendarEnabled,
416
+ eventDate,
417
+ eventDurationMinutes,
418
+ eventLocation,
419
+ eventTime,
420
+ eventTitle,
421
+ refresh,
422
+ setActionNotice,
423
+ status,
424
+ t,
425
+ timeZone,
426
+ ]);
427
+ const handleGenerateDraft = useCallback(async () => {
428
+ if (!status || !emailEnabled || !selectedGmailMessage) {
429
+ return;
430
+ }
431
+ setDrafting(true);
432
+ setError(null);
433
+ try {
434
+ const response = await client.createLifeOpsGmailReplyDraft({
435
+ side: status.side,
436
+ mode: status.mode,
437
+ messageId: selectedGmailMessage.id,
438
+ tone: draftTone,
439
+ includeQuotedOriginal: true,
440
+ });
441
+ setDraft(response.draft);
442
+ setDraftBody(response.draft.bodyText);
443
+ setSendConfirmed(false);
444
+ setActionNotice(t("lifeopsworkspace.draftedReply", {
445
+ defaultValue: "Drafted {{subject}}",
446
+ subject: selectedGmailMessage.subject,
447
+ }), "success", 2200);
448
+ }
449
+ catch (cause) {
450
+ setError(cause instanceof Error && cause.message.trim().length > 0
451
+ ? cause.message.trim()
452
+ : t("lifeopsworkspace.draftReplyFailed", {
453
+ defaultValue: "Could not draft the reply.",
454
+ }));
455
+ }
456
+ finally {
457
+ setDrafting(false);
458
+ }
459
+ }, [
460
+ draftTone,
461
+ emailEnabled,
462
+ selectedGmailMessage,
463
+ setActionNotice,
464
+ status,
465
+ t,
466
+ ]);
467
+ const handleSearchGmail = useCallback(async () => {
468
+ if (!status || !emailEnabled) {
469
+ return;
470
+ }
471
+ const query = gmailQuery.trim();
472
+ if (!query) {
473
+ setError(t("lifeopsworkspace.gmailSearchValidation", {
474
+ defaultValue: "Enter a Gmail search query.",
475
+ }));
476
+ return;
477
+ }
478
+ setLoading(true);
479
+ setError(null);
480
+ try {
481
+ const result = await client.getLifeOpsGmailSearch({
482
+ side: status.side,
483
+ mode: status.mode,
484
+ query,
485
+ maxResults: GMAIL_BULK_MESSAGE_LIMIT,
486
+ forceSync: true,
487
+ replyNeededOnly: gmailReplyNeededOnly,
488
+ includeSpamTrash: gmailIncludeSpamTrash,
489
+ });
490
+ setGmailFeed(result);
491
+ setGmailRecommendations(null);
492
+ setGmailSelectedMessageIds([]);
493
+ setGmailManageConfirmed(false);
494
+ }
495
+ catch (cause) {
496
+ setError(cause instanceof Error && cause.message.trim().length > 0
497
+ ? cause.message.trim()
498
+ : t("lifeopsworkspace.gmailSearchFailed", {
499
+ defaultValue: "Could not search Gmail.",
500
+ }));
501
+ }
502
+ finally {
503
+ setLoading(false);
504
+ }
505
+ }, [
506
+ emailEnabled,
507
+ gmailIncludeSpamTrash,
508
+ gmailQuery,
509
+ gmailReplyNeededOnly,
510
+ status,
511
+ t,
512
+ ]);
513
+ const handleShowNeedsResponse = useCallback(async () => {
514
+ if (!status || !emailEnabled) {
515
+ return;
516
+ }
517
+ setLoading(true);
518
+ setError(null);
519
+ try {
520
+ const result = await client.getLifeOpsGmailNeedsResponse({
521
+ side: status.side,
522
+ mode: status.mode,
523
+ maxResults: GMAIL_BULK_MESSAGE_LIMIT,
524
+ forceSync: true,
525
+ });
526
+ setGmailFeed(result);
527
+ setGmailRecommendations(null);
528
+ setGmailSelectedMessageIds([]);
529
+ setGmailManageConfirmed(false);
530
+ }
531
+ catch (cause) {
532
+ setError(cause instanceof Error && cause.message.trim().length > 0
533
+ ? cause.message.trim()
534
+ : t("lifeopsworkspace.gmailNeedsResponseFailed", {
535
+ defaultValue: "Could not load Gmail messages that need response.",
536
+ }));
537
+ }
538
+ finally {
539
+ setLoading(false);
540
+ }
541
+ }, [emailEnabled, status, t]);
542
+ const handleLoadRecommendations = useCallback(async () => {
543
+ if (!status || !emailEnabled) {
544
+ return;
545
+ }
546
+ setLoading(true);
547
+ setError(null);
548
+ try {
549
+ const result = await client.getLifeOpsGmailRecommendations({
550
+ side: status.side,
551
+ mode: status.mode,
552
+ query: gmailQuery.trim() || undefined,
553
+ maxResults: GMAIL_BULK_MESSAGE_LIMIT,
554
+ forceSync: true,
555
+ replyNeededOnly: gmailReplyNeededOnly,
556
+ includeSpamTrash: gmailIncludeSpamTrash,
557
+ });
558
+ setGmailRecommendations(result);
559
+ setGmailManageConfirmed(false);
560
+ }
561
+ catch (cause) {
562
+ setError(cause instanceof Error && cause.message.trim().length > 0
563
+ ? cause.message.trim()
564
+ : t("lifeopsworkspace.gmailRecommendationsFailed", {
565
+ defaultValue: "Could not load Gmail recommendations.",
566
+ }));
567
+ }
568
+ finally {
569
+ setLoading(false);
570
+ }
571
+ }, [
572
+ emailEnabled,
573
+ gmailIncludeSpamTrash,
574
+ gmailQuery,
575
+ gmailReplyNeededOnly,
576
+ status,
577
+ t,
578
+ ]);
579
+ const handleSendDraft = useCallback(async () => {
580
+ if (!status || !selectedGmailMessage || draftBody.trim().length === 0) {
581
+ return;
582
+ }
583
+ if (!sendConfirmed) {
584
+ setError(t("lifeopsworkspace.sendConfirmationRequired", {
585
+ defaultValue: "Confirm this Gmail send before sending.",
586
+ }));
587
+ return;
588
+ }
589
+ setSending(true);
590
+ setError(null);
591
+ try {
592
+ await client.sendLifeOpsGmailReply({
593
+ side: status.side,
594
+ mode: status.mode,
595
+ messageId: selectedGmailMessage.id,
596
+ bodyText: draftBody,
597
+ confirmSend: true,
598
+ subject: draft?.subject,
599
+ to: draft?.to,
600
+ cc: draft?.cc,
601
+ });
602
+ setActionNotice(t("lifeopsworkspace.sentReply", {
603
+ defaultValue: "Sent {{subject}}",
604
+ subject: selectedGmailMessage.subject,
605
+ }), "success", 2400);
606
+ setDraft(null);
607
+ setDraftBody("");
608
+ setSendConfirmed(false);
609
+ await refresh();
610
+ }
611
+ catch (cause) {
612
+ setError(cause instanceof Error && cause.message.trim().length > 0
613
+ ? cause.message.trim()
614
+ : t("lifeopsworkspace.sendReplyFailed", {
615
+ defaultValue: "Could not send the reply.",
616
+ }));
617
+ }
618
+ finally {
619
+ setSending(false);
620
+ }
621
+ }, [
622
+ draft,
623
+ draftBody,
624
+ refresh,
625
+ selectedGmailMessage,
626
+ sendConfirmed,
627
+ setActionNotice,
628
+ status,
629
+ t,
630
+ ]);
631
+ const toggleGmailMessageSelection = useCallback((messageId) => {
632
+ setGmailManageConfirmed(false);
633
+ setGmailSelectedMessageIds((current) => current.includes(messageId)
634
+ ? current.filter((id) => id !== messageId)
635
+ : [...current, messageId]);
636
+ }, []);
637
+ const handleManageMessage = useCallback(async (operation, options = {}) => {
638
+ if (!status || !emailManageEnabled) {
639
+ return;
640
+ }
641
+ const messageIds = options.messageIds ??
642
+ (gmailSelectedMessageIds.length > 0
643
+ ? gmailSelectedMessageIds
644
+ : selectedGmailMessage
645
+ ? [selectedGmailMessage.id]
646
+ : []);
647
+ if (messageIds.length === 0) {
648
+ setError(t("lifeopsworkspace.gmailSelectMessages", {
649
+ defaultValue: "Select at least one Gmail message.",
650
+ }));
651
+ return;
652
+ }
653
+ const labelIds = options.labelIds ??
654
+ (operation === "apply_label" || operation === "remove_label"
655
+ ? parseGmailLabelIds(gmailLabelIds)
656
+ : []);
657
+ if ((operation === "apply_label" || operation === "remove_label") &&
658
+ labelIds.length === 0) {
659
+ setError(t("lifeopsworkspace.gmailLabelValidation", {
660
+ defaultValue: "Enter at least one Gmail label ID.",
661
+ }));
662
+ return;
663
+ }
664
+ const requiresConfirmation = options.requiresConfirmation === true ||
665
+ messageIds.length > 1 ||
666
+ isDestructiveGmailOperation(operation);
667
+ if (requiresConfirmation && !gmailManageConfirmed) {
668
+ setError(t("lifeopsworkspace.gmailManageConfirmationRequired", {
669
+ defaultValue: "Confirm this bulk or destructive Gmail update before running it.",
670
+ }));
671
+ return;
672
+ }
673
+ setManaging(true);
674
+ setError(null);
675
+ try {
676
+ const result = await client.manageLifeOpsGmailMessages({
677
+ side: status.side,
678
+ mode: status.mode,
679
+ messageIds,
680
+ operation,
681
+ labelIds,
682
+ confirmDestructive: isDestructiveGmailOperation(operation),
683
+ });
684
+ setActionNotice(t("lifeopsworkspace.gmailManaged", {
685
+ defaultValue: "{{operation}} applied to {{count}} message",
686
+ operation: result.operation,
687
+ count: result.affectedCount,
688
+ }), "success", 2200);
689
+ setGmailSelectedMessageIds([]);
690
+ setGmailManageConfirmed(false);
691
+ setDraft(null);
692
+ setDraftBody("");
693
+ setSendConfirmed(false);
694
+ await refresh();
695
+ }
696
+ catch (cause) {
697
+ setError(cause instanceof Error && cause.message.trim().length > 0
698
+ ? cause.message.trim()
699
+ : t("lifeopsworkspace.gmailManageFailed", {
700
+ defaultValue: "Could not update the Gmail message.",
701
+ }));
702
+ }
703
+ finally {
704
+ setManaging(false);
705
+ }
706
+ }, [
707
+ emailManageEnabled,
708
+ gmailLabelIds,
709
+ gmailManageConfirmed,
710
+ gmailSelectedMessageIds,
711
+ refresh,
712
+ selectedGmailMessage,
713
+ setActionNotice,
714
+ status,
715
+ t,
716
+ ]);
717
+ const handleApplyRecommendation = useCallback(async (recommendation) => {
718
+ if (!recommendation.operation) {
719
+ return;
720
+ }
721
+ await handleManageMessage(recommendation.operation, {
722
+ messageIds: recommendation.messageIds,
723
+ labelIds: recommendation.labelIds,
724
+ requiresConfirmation: recommendation.requiresConfirmation,
725
+ });
726
+ }, [handleManageMessage]);
727
+ return {
728
+ side,
729
+ identity,
730
+ status,
731
+ connected,
732
+ statusLabel: connectorStatusLabel(status, t),
733
+ loading,
734
+ error,
735
+ calendarEnabled,
736
+ emailEnabled,
737
+ emailManageEnabled,
738
+ calendarEvents,
739
+ groupedCalendarEvents,
740
+ selectedCalendarEvent,
741
+ setSelectedCalendarId,
742
+ refresh,
743
+ gmailMessages,
744
+ selectedGmailMessage,
745
+ setSelectedMessageId: handleSelectGmailMessage,
746
+ gmailRecommendations,
747
+ gmailQuery,
748
+ setGmailQuery,
749
+ gmailReplyNeededOnly,
750
+ setGmailReplyNeededOnly,
751
+ gmailIncludeSpamTrash,
752
+ setGmailIncludeSpamTrash,
753
+ gmailSelectedMessageIds,
754
+ toggleGmailMessageSelection,
755
+ gmailLabelIds,
756
+ setGmailLabelIds,
757
+ gmailManageConfirmed,
758
+ setGmailManageConfirmed,
759
+ draftTone,
760
+ setDraftTone,
761
+ draft,
762
+ draftBody,
763
+ setDraftBody,
764
+ sendConfirmed,
765
+ setSendConfirmed,
766
+ drafting,
767
+ sending,
768
+ managing,
769
+ eventTitle,
770
+ setEventTitle,
771
+ eventDate,
772
+ setEventDate,
773
+ eventTime,
774
+ setEventTime,
775
+ eventDurationMinutes,
776
+ setEventDurationMinutes,
777
+ eventLocation,
778
+ setEventLocation,
779
+ creatingEvent,
780
+ handleCreateEvent,
781
+ handleGenerateDraft,
782
+ handleSearchGmail,
783
+ handleShowNeedsResponse,
784
+ handleLoadRecommendations,
785
+ handleSendDraft,
786
+ handleManageMessage,
787
+ handleApplyRecommendation,
788
+ };
789
+ }
790
+ function SectionShell({ title, actions, children, }) {
791
+ return (_jsxs("section", { className: "overflow-hidden rounded-3xl border border-border/16 bg-card/18", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 px-4 py-4", children: [_jsx("div", { className: "text-sm font-semibold text-txt", children: title }), actions] }), _jsx("div", { className: "border-t border-border/12 px-4 py-4", children: children })] }));
792
+ }
793
+ function LockedSection({ title, hint, owner, agent, t, }) {
794
+ return (_jsxs(SectionShell, { title: title, children: [_jsx("div", { className: "mb-3 text-xs leading-5 text-muted", children: hint }), _jsx("div", { className: "grid gap-4 lg:grid-cols-2", children: [owner, agent].map((workspace) => (_jsxs("div", { className: "rounded-2xl bg-bg/36 px-4 py-4", children: [_jsx("div", { className: "text-sm font-semibold text-txt", children: sideLabel(workspace.side, t) }), _jsx("div", { className: "mt-1 text-xs text-muted", children: workspace.statusLabel })] }, workspace.side))) })] }));
795
+ }
796
+ function AccountBadge({ label }) {
797
+ if (!label) {
798
+ return null;
799
+ }
800
+ return (_jsx(Badge, { variant: "outline", className: "text-3xs", children: label }));
801
+ }
802
+ function CalendarColumn({ workspace, timeZone, t, }) {
803
+ const [composerOpen, setComposerOpen] = useState(false);
804
+ const eventCount = workspace.calendarEvents.length;
805
+ return (_jsxs("div", { className: "space-y-4 rounded-2xl bg-bg/36 px-4 py-4", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-sm font-semibold text-txt", children: sideLabel(workspace.side, t) }), _jsx("div", { className: "mt-1 truncate text-xs text-muted", children: workspace.identity.secondary ?? workspace.identity.primary })] }), _jsx(Badge, { variant: "outline", className: "text-2xs", children: eventCount })] }), workspace.error ? (_jsx("div", { className: "rounded-2xl bg-danger/10 px-3 py-2 text-xs text-danger", children: workspace.error })) : null, !workspace.calendarEnabled ? (_jsx("div", { className: "text-xs text-muted", children: t("lifeopsworkspace.grantCalendarAccess", {
806
+ defaultValue: "Grant calendar access for this Google account in Setup.",
807
+ }) })) : workspace.loading && eventCount === 0 ? (_jsx("div", { className: "text-xs text-muted", children: t("lifeopsworkspace.loadingEvents", {
808
+ defaultValue: "Loading events…",
809
+ }) })) : eventCount === 0 ? (_jsx("div", { className: "text-xs text-muted", children: t("lifeopsworkspace.nothingScheduled", {
810
+ defaultValue: "Nothing scheduled. Use New event below to add one.",
811
+ }) })) : (_jsx("div", { className: "space-y-3", children: workspace.groupedCalendarEvents.map((group) => (_jsxs("div", { className: "space-y-2", children: [_jsx("div", { className: "text-xs font-semibold uppercase tracking-[0.12em] text-muted", children: group.label }), _jsx("div", { className: "overflow-hidden rounded-2xl bg-bg/45", children: group.events.map((event, index) => (_jsxs("button", { type: "button", onClick: () => workspace.setSelectedCalendarId(event.id), className: `flex w-full items-start justify-between gap-3 px-3 py-3 text-left ${index > 0 ? "border-t border-border/12" : ""} ${workspace.selectedCalendarEvent?.id === event.id
812
+ ? "bg-accent/8"
813
+ : "hover:bg-bg-hover/30"}`, children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "truncate text-sm font-medium text-txt", children: event.title }), _jsx("div", { className: "mt-1 text-xs text-muted", children: formatEventWindow(event, t, timeZone) }), event.location.trim().length > 0 ? (_jsx("div", { className: "mt-1 truncate text-xs text-muted/90", children: event.location })) : null] }), _jsx("div", { className: "flex flex-col items-end gap-1", children: _jsx(AccountBadge, { label: eventOriginLabel(event) }) })] }, event.id))) })] }, group.dayKey))) })), workspace.selectedCalendarEvent ? (_jsxs("div", { className: "space-y-2 rounded-2xl bg-card/18 px-3 py-3 text-xs text-muted", children: [_jsx("div", { className: "text-sm font-semibold text-txt", children: workspace.selectedCalendarEvent.title }), _jsx("div", { children: formatLocalDateTime(workspace.selectedCalendarEvent.startAt, timeZone) }), workspace.selectedCalendarEvent.location.trim().length > 0 ? (_jsx("div", { children: workspace.selectedCalendarEvent.location })) : null, workspace.selectedCalendarEvent.conferenceLink ? (_jsx("div", { className: "truncate", children: workspace.selectedCalendarEvent.conferenceLink })) : null, _jsx(AccountBadge, { label: eventOriginLabel(workspace.selectedCalendarEvent) })] })) : null, workspace.calendarEnabled ? (_jsxs("div", { className: "space-y-3", children: [_jsx(Button, { size: "sm", variant: "outline", className: "h-8 rounded-xl px-3 text-xs font-semibold", onClick: () => setComposerOpen((current) => !current), children: composerOpen
814
+ ? t("lifeopsworkspace.hideNewEvent", {
815
+ defaultValue: "Hide new event",
816
+ })
817
+ : t("lifeopsworkspace.newEvent", {
818
+ defaultValue: "New event",
819
+ }) }), composerOpen ? (_jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [_jsx(Input, { value: workspace.eventTitle, onChange: (event) => workspace.setEventTitle(event.target.value), placeholder: t("common.title", {
820
+ defaultValue: "Title",
821
+ }), "aria-label": t("lifeopsworkspace.eventTitle", {
822
+ defaultValue: "Event title",
823
+ }), className: "sm:col-span-2" }), _jsx(Input, { type: "date", value: workspace.eventDate, onChange: (event) => workspace.setEventDate(event.target.value), "aria-label": t("lifeopsworkspace.eventDate", {
824
+ defaultValue: "Event date",
825
+ }) }), _jsx(Input, { type: "time", value: workspace.eventTime, onChange: (event) => workspace.setEventTime(event.target.value), "aria-label": t("lifeopsworkspace.eventStartTime", {
826
+ defaultValue: "Event start time",
827
+ }) }), _jsx(Input, { type: "number", min: 5, step: 5, value: workspace.eventDurationMinutes, onChange: (event) => workspace.setEventDurationMinutes(event.target.value), placeholder: t("lifeopsworkspace.durationMinutes", {
828
+ defaultValue: "Duration in minutes",
829
+ }), "aria-label": t("lifeopsworkspace.durationMinutes", {
830
+ defaultValue: "Duration in minutes",
831
+ }) }), _jsx(Input, { value: workspace.eventLocation, onChange: (event) => workspace.setEventLocation(event.target.value), placeholder: t("lifeopsworkspace.locationOptional", {
832
+ defaultValue: "Location (optional)",
833
+ }), "aria-label": t("common.location", {
834
+ defaultValue: "Location",
835
+ }) }), _jsx(Button, { size: "sm", className: "h-9 rounded-xl px-3 text-xs font-semibold sm:col-span-2", disabled: workspace.creatingEvent || !workspace.eventTitle.trim(), onClick: () => void workspace.handleCreateEvent(), children: workspace.creatingEvent
836
+ ? t("lifeopsworkspace.creating", {
837
+ defaultValue: "Creating…",
838
+ })
839
+ : t("lifeopsworkspace.createEvent", {
840
+ defaultValue: "Create event",
841
+ }) })] })) : null] })) : null] }));
842
+ }
843
+ function GmailControls({ workspace, t, }) {
844
+ return (_jsxs("div", { className: "space-y-2 rounded-2xl bg-card/18 px-3 py-3", children: [_jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Input, { value: workspace.gmailQuery, onChange: (event) => workspace.setGmailQuery(event.target.value), placeholder: t("lifeopsworkspace.gmailSearchPlaceholder", {
845
+ defaultValue: "Gmail query, e.g. in:inbox newer_than:7d",
846
+ }), "aria-label": t("lifeopsworkspace.gmailSearchQuery", {
847
+ defaultValue: "Gmail search query",
848
+ }), className: "h-8 min-w-48 flex-1 text-xs" }), _jsx(Button, { size: "sm", variant: "outline", className: "h-8 rounded-xl px-3 text-xs font-semibold", disabled: workspace.loading || workspace.gmailQuery.trim().length === 0, onClick: () => void workspace.handleSearchGmail(), children: t("lifeopsworkspace.searchGmail", {
849
+ defaultValue: "Search Gmail",
850
+ }) }), _jsx(Button, { size: "sm", variant: "outline", className: "h-8 rounded-xl px-3 text-xs font-semibold", disabled: workspace.loading, onClick: () => void workspace.refresh(), children: t("lifeopsworkspace.refreshInbox", {
851
+ defaultValue: "Refresh inbox",
852
+ }) })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-3 text-xs text-muted", children: [_jsxs("label", { className: "inline-flex items-center gap-1.5", children: [_jsx("input", { type: "checkbox", checked: workspace.gmailReplyNeededOnly, onChange: (event) => workspace.setGmailReplyNeededOnly(event.target.checked) }), t("lifeopsworkspace.replyNeededOnly", {
853
+ defaultValue: "Reply-needed only",
854
+ })] }), _jsxs("label", { className: "inline-flex items-center gap-1.5", children: [_jsx("input", { type: "checkbox", checked: workspace.gmailIncludeSpamTrash, onChange: (event) => workspace.setGmailIncludeSpamTrash(event.target.checked) }), t("lifeopsworkspace.includeSpamTrash", {
855
+ defaultValue: "Include spam/trash",
856
+ })] }), _jsx(Button, { size: "sm", variant: "ghost", className: "h-8 rounded-xl px-3 text-xs font-semibold", disabled: workspace.loading, onClick: () => void workspace.handleShowNeedsResponse(), children: t("lifeopsworkspace.needsResponse", {
857
+ defaultValue: "Needs response",
858
+ }) }), _jsx(Button, { size: "sm", variant: "ghost", className: "h-8 rounded-xl px-3 text-xs font-semibold", disabled: workspace.loading, onClick: () => void workspace.handleLoadRecommendations(), children: t("lifeopsworkspace.recommendations", {
859
+ defaultValue: "Recommendations",
860
+ }) })] })] }));
861
+ }
862
+ function GmailRecommendationsPanel({ workspace, t, }) {
863
+ const recommendations = workspace.gmailRecommendations?.recommendations ?? [];
864
+ const needsConfirmation = recommendations.some((recommendation) => recommendation.requiresConfirmation ||
865
+ recommendation.kind === "review_spam" ||
866
+ (recommendation.operation
867
+ ? recommendation.messageIds.length > 1 ||
868
+ isDestructiveGmailOperation(recommendation.operation)
869
+ : false));
870
+ if (recommendations.length === 0) {
871
+ return (_jsx("div", { className: "rounded-2xl bg-card/18 px-3 py-3 text-xs text-muted", children: t("lifeopsworkspace.noGmailRecommendations", {
872
+ defaultValue: "No Gmail recommendations for this query.",
873
+ }) }));
874
+ }
875
+ return (_jsxs("div", { className: "space-y-2 rounded-2xl bg-card/18 px-3 py-3", children: [_jsx("div", { className: "text-xs font-semibold uppercase tracking-[0.12em] text-muted", children: t("lifeopsworkspace.gmailRecommendations", {
876
+ defaultValue: "Gmail recommendations",
877
+ }) }), needsConfirmation ? (_jsxs("label", { className: "inline-flex items-center gap-1.5 text-xs text-muted", children: [_jsx("input", { type: "checkbox", checked: workspace.gmailManageConfirmed, onChange: (event) => workspace.setGmailManageConfirmed(event.target.checked) }), t("lifeopsworkspace.confirmGmailRecommendation", {
878
+ defaultValue: "Confirm recommendation update",
879
+ })] })) : null, recommendations.map((recommendation) => (_jsxs("div", { className: "space-y-2 rounded-2xl bg-bg/40 px-3 py-3", children: [_jsxs("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-sm font-semibold text-txt", children: recommendation.title }), _jsx("div", { className: "mt-1 text-xs text-muted", children: recommendation.rationale })] }), _jsx(Badge, { variant: "outline", className: "text-3xs", children: recommendation.affectedCount })] }), recommendation.sampleMessages.length > 0 ? (_jsx("div", { className: "space-y-1", children: recommendation.sampleMessages.slice(0, 3).map((message) => (_jsxs("div", { className: "text-xs text-muted", children: [_jsx("span", { className: "font-medium text-txt/85", children: message.subject }), " ", message.from] }, message.messageId))) })) : null, _jsxs("div", { className: "flex flex-wrap gap-2", children: [recommendation.operation ? (_jsx(Button, { size: "sm", variant: "outline", className: "h-8 rounded-xl px-3 text-xs font-semibold", disabled: workspace.managing ||
880
+ ((recommendation.requiresConfirmation ||
881
+ recommendation.messageIds.length > 1 ||
882
+ isDestructiveGmailOperation(recommendation.operation)) &&
883
+ !workspace.gmailManageConfirmed), onClick: () => void workspace.handleApplyRecommendation(recommendation), children: gmailOperationLabel(recommendation.operation, t) })) : null, recommendation.kind === "review_spam"
884
+ ? recommendation.sampleMessages.map((message) => (_jsx(Button, { size: "sm", variant: "outline", className: "h-8 rounded-xl px-3 text-xs font-semibold", disabled: workspace.managing || !workspace.gmailManageConfirmed, onClick: () => void workspace.handleManageMessage("report_spam", {
885
+ messageIds: [message.messageId],
886
+ }), children: t("lifeopsworkspace.reportSampleSpam", {
887
+ defaultValue: "Report sample spam",
888
+ }) }, message.messageId)))
889
+ : null] })] }, recommendation.id)))] }));
890
+ }
891
+ function EmailColumn({ workspace, timeZone, t, }) {
892
+ const messageCount = workspace.gmailMessages.length;
893
+ const selectedBulkMessageIds = workspace.gmailSelectedMessageIds.length > 0
894
+ ? workspace.gmailSelectedMessageIds
895
+ : workspace.selectedGmailMessage
896
+ ? [workspace.selectedGmailMessage.id]
897
+ : [];
898
+ const selectedBulkCount = selectedBulkMessageIds.length;
899
+ const labelIds = parseGmailLabelIds(workspace.gmailLabelIds);
900
+ const isManageDisabled = (operation) => {
901
+ if (workspace.managing || selectedBulkCount === 0) {
902
+ return true;
903
+ }
904
+ if ((operation === "apply_label" || operation === "remove_label") &&
905
+ labelIds.length === 0) {
906
+ return true;
907
+ }
908
+ if ((selectedBulkCount > 1 || isDestructiveGmailOperation(operation)) &&
909
+ !workspace.gmailManageConfirmed) {
910
+ return true;
911
+ }
912
+ return false;
913
+ };
914
+ return (_jsxs("div", { className: "space-y-4 rounded-2xl bg-bg/36 px-4 py-4", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-sm font-semibold text-txt", children: sideLabel(workspace.side, t) }), _jsx("div", { className: "mt-1 truncate text-xs text-muted", children: workspace.identity.secondary ?? workspace.identity.primary })] }), _jsx(Badge, { variant: "outline", className: "text-2xs", children: messageCount })] }), workspace.error ? (_jsx("div", { className: "rounded-2xl bg-danger/10 px-3 py-2 text-xs text-danger", children: workspace.error })) : null, !workspace.emailEnabled ? (_jsx("div", { className: "text-xs text-muted", children: t("lifeopsworkspace.grantGmailAccess", {
915
+ defaultValue: "Grant Gmail access for this Google account in Setup.",
916
+ }) })) : messageCount === 0 ? (_jsxs("div", { className: "space-y-3", children: [_jsx(GmailControls, { workspace: workspace, t: t }), _jsx("div", { className: "text-xs text-muted", children: workspace.loading
917
+ ? t("lifeopsworkspace.loadingRecentMail", {
918
+ defaultValue: "Loading recent mail…",
919
+ })
920
+ : t("lifeopsworkspace.inboxClear", {
921
+ defaultValue: "Inbox clear. Nothing to triage right now.",
922
+ }) })] })) : (_jsxs("div", { className: "space-y-3", children: [_jsx(GmailControls, { workspace: workspace, t: t }), _jsx("div", { className: "overflow-hidden rounded-2xl bg-bg/45", children: workspace.gmailMessages.map((message, index) => (_jsxs("div", { className: `flex w-full items-start justify-between gap-3 px-3 py-3 text-left ${index > 0 ? "border-t border-border/12" : ""} ${workspace.selectedGmailMessage?.id === message.id
923
+ ? "bg-accent/8"
924
+ : "hover:bg-bg-hover/30"}`, children: [_jsx("label", { className: "mt-1 inline-flex shrink-0 items-center", children: _jsx("input", { type: "checkbox", checked: workspace.gmailSelectedMessageIds.includes(message.id), onChange: () => workspace.toggleGmailMessageSelection(message.id), "aria-label": t("lifeopsworkspace.selectGmailMessage", {
925
+ defaultValue: "Select Gmail message {{subject}}",
926
+ subject: message.subject,
927
+ }) }) }), _jsxs("button", { type: "button", onClick: () => workspace.setSelectedMessageId(message.id), className: "min-w-0 flex flex-1 items-start justify-between gap-3 text-left", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "truncate text-sm font-medium text-txt", children: message.subject }), _jsx("div", { className: "mt-1 truncate text-xs text-muted", children: message.from }), _jsx("div", { className: "mt-1 line-clamp-2 text-xs text-muted/90", children: message.snippet })] }), _jsxs("div", { className: "flex flex-col items-end gap-1", children: [message.likelyReplyNeeded ? (_jsx(Badge, { variant: "secondary", className: "text-3xs", children: t("lifeopsworkspace.reply", {
928
+ defaultValue: "Reply",
929
+ }) })) : null, message.isUnread ? (_jsx(Badge, { variant: "outline", className: "text-3xs", children: t("lifeopsworkspace.unread", {
930
+ defaultValue: "Unread",
931
+ }) })) : null, _jsx(AccountBadge, { label: message.accountEmail }), _jsx("div", { className: "text-[11px] text-muted", children: formatLocalDateTime(message.receivedAt, timeZone) })] })] })] }, message.id))) })] })), workspace.selectedGmailMessage ? (_jsxs("div", { className: "space-y-3 rounded-2xl bg-card/18 px-3 py-3", children: [_jsxs("div", { className: "space-y-1 text-xs text-muted", children: [_jsx("div", { className: "text-sm font-semibold text-txt", children: workspace.selectedGmailMessage.subject }), _jsx("div", { children: workspace.selectedGmailMessage.from }), _jsx("div", { children: workspace.selectedGmailMessage.snippet })] }), workspace.emailManageEnabled ? (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2 text-xs text-muted", children: [_jsx("span", { children: t("lifeopsworkspace.gmailManageTarget", {
932
+ defaultValue: selectedBulkCount > 1
933
+ ? "{{count}} selected messages"
934
+ : "Selected message",
935
+ count: selectedBulkCount,
936
+ }) }), _jsxs("label", { className: "inline-flex items-center gap-1.5", children: [_jsx("input", { type: "checkbox", checked: workspace.gmailManageConfirmed, onChange: (event) => workspace.setGmailManageConfirmed(event.target.checked) }), t("lifeopsworkspace.confirmGmailManage", {
937
+ defaultValue: "Confirm bulk/destructive update",
938
+ })] })] }), _jsx("div", { className: "flex flex-wrap gap-2", children: [
939
+ "archive",
940
+ "mark_read",
941
+ "mark_unread",
942
+ "report_spam",
943
+ "trash",
944
+ ].map((operation) => (_jsx(Button, { size: "sm", variant: "outline", className: "h-8 rounded-xl px-3 text-xs font-semibold", disabled: isManageDisabled(operation), onClick: () => void workspace.handleManageMessage(operation), children: gmailOperationLabel(operation, t) }, operation))) }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Input, { value: workspace.gmailLabelIds, onChange: (event) => workspace.setGmailLabelIds(event.target.value), placeholder: t("lifeopsworkspace.gmailLabelIds", {
945
+ defaultValue: "Label ID(s), comma-separated",
946
+ }), "aria-label": t("lifeopsworkspace.gmailLabelIds", {
947
+ defaultValue: "Label ID(s), comma-separated",
948
+ }), className: "h-8 min-w-48 flex-1 text-xs" }), ["apply_label", "remove_label"].map((operation) => (_jsx(Button, { size: "sm", variant: "outline", className: "h-8 rounded-xl px-3 text-xs font-semibold", disabled: isManageDisabled(operation), onClick: () => void workspace.handleManageMessage(operation), children: gmailOperationLabel(operation, t) }, operation)))] })] })) : null, _jsx(SegmentedControl, { "aria-label": t("lifeopsworkspace.draftToneAria", {
949
+ defaultValue: "{{side}} draft tone",
950
+ side: sideLabel(workspace.side, t),
951
+ }), value: workspace.draftTone, onValueChange: workspace.setDraftTone, items: [
952
+ {
953
+ value: "brief",
954
+ label: t("lifeopsworkspace.brief", {
955
+ defaultValue: "Brief",
956
+ }),
957
+ },
958
+ {
959
+ value: "neutral",
960
+ label: t("lifeopsworkspace.neutral", {
961
+ defaultValue: "Neutral",
962
+ }),
963
+ },
964
+ {
965
+ value: "warm",
966
+ label: t("lifeopsworkspace.warm", {
967
+ defaultValue: "Warm",
968
+ }),
969
+ },
970
+ ], className: "border-border/28 bg-card/24 p-0.5", buttonClassName: "min-h-8 px-3 py-1.5 text-xs" }), _jsx(Textarea, { value: workspace.draftBody, onChange: (event) => {
971
+ workspace.setDraftBody(event.target.value);
972
+ workspace.setSendConfirmed(false);
973
+ }, placeholder: t("lifeopsworkspace.reply", {
974
+ defaultValue: "Reply",
975
+ }), className: "min-h-32" }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { size: "sm", className: "h-8 rounded-xl px-3 text-xs font-semibold", disabled: workspace.drafting, onClick: () => void workspace.handleGenerateDraft(), children: workspace.drafting
976
+ ? t("lifeopsworkspace.drafting", {
977
+ defaultValue: "Drafting...",
978
+ })
979
+ : t("lifeopsworkspace.draftReply", {
980
+ defaultValue: "Draft reply",
981
+ }) }), _jsx(Button, { size: "sm", variant: "outline", className: "h-8 rounded-xl px-3 text-xs font-semibold", disabled: workspace.sending ||
982
+ workspace.draftBody.trim().length === 0 ||
983
+ !workspace.sendConfirmed, onClick: () => void workspace.handleSendDraft(), children: workspace.sending
984
+ ? t("lifeopsworkspace.sending", {
985
+ defaultValue: "Sending...",
986
+ })
987
+ : t("common.send", {
988
+ defaultValue: "Send",
989
+ }) })] }), _jsxs("label", { className: "inline-flex items-center gap-2 text-xs text-muted", children: [_jsx("input", { type: "checkbox", checked: workspace.sendConfirmed, onChange: (event) => workspace.setSendConfirmed(event.target.checked) }), t("lifeopsworkspace.confirmSendGmailReply", {
990
+ defaultValue: "Confirm sending this Gmail reply now",
991
+ })] }), workspace.draft ? (_jsx("div", { className: "text-xs text-muted", children: t("lifeopsworkspace.gmailDraftCreatedNoAutoSend", {
992
+ defaultValue: "Draft created. It will not send until you confirm and press Send.",
993
+ }) })) : null] })) : null, workspace.gmailRecommendations ? (_jsx(GmailRecommendationsPanel, { workspace: workspace, t: t })) : null] }));
994
+ }
995
+ export function LifeOpsWorkspaceView() {
996
+ const { t } = useApp();
997
+ const timeZone = useMemo(() => Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC", []);
998
+ const [calendarWindow, setCalendarWindow] = useState("today");
999
+ const owner = useLifeOpsSideWorkspace({
1000
+ side: "owner",
1001
+ calendarWindow,
1002
+ timeZone,
1003
+ });
1004
+ const agent = useLifeOpsSideWorkspace({
1005
+ side: "agent",
1006
+ calendarWindow,
1007
+ timeZone,
1008
+ });
1009
+ const workspaceReady = owner.connected && agent.connected;
1010
+ if (!workspaceReady) {
1011
+ return (_jsxs("div", { className: "space-y-6", children: [_jsx(LockedSection, { title: t("lifeopsworkspace.calendar", {
1012
+ defaultValue: "Calendar",
1013
+ }), hint: t("lifeopsworkspace.calendarLockedHint", {
1014
+ defaultValue: "Connect Google for both User and Agent in Setup above to see today's events and create new ones here.",
1015
+ }), owner: owner, agent: agent, t: t }), _jsx(LockedSection, { title: t("lifeopsworkspace.email", {
1016
+ defaultValue: "Email",
1017
+ }), hint: t("lifeopsworkspace.emailLockedHint", {
1018
+ defaultValue: "Connect Google for both User and Agent in Setup above to triage replies and draft responses here.",
1019
+ }), owner: owner, agent: agent, t: t })] }));
1020
+ }
1021
+ return (_jsxs("div", { className: "space-y-6", children: [_jsx(SectionShell, { title: t("lifeopsworkspace.calendar", {
1022
+ defaultValue: "Calendar",
1023
+ }), actions: _jsx(SegmentedControl, { "aria-label": t("lifeopsworkspace.calendarWindow", {
1024
+ defaultValue: "Calendar window",
1025
+ }), value: calendarWindow, onValueChange: setCalendarWindow, items: [
1026
+ {
1027
+ value: "today",
1028
+ label: t("lifeopsworkspace.today", {
1029
+ defaultValue: "Today",
1030
+ }),
1031
+ },
1032
+ {
1033
+ value: "week",
1034
+ label: t("lifeopsworkspace.week", {
1035
+ defaultValue: "Week",
1036
+ }),
1037
+ },
1038
+ ], className: "border-border/28 bg-card/24 p-0.5", buttonClassName: "min-h-8 px-3 py-1.5 text-xs" }), children: _jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [_jsx(CalendarColumn, { workspace: owner, timeZone: timeZone, t: t }), _jsx(CalendarColumn, { workspace: agent, timeZone: timeZone, t: t })] }) }), _jsx(SectionShell, { title: t("lifeopsworkspace.email", {
1039
+ defaultValue: "Email",
1040
+ }), children: _jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [_jsx(EmailColumn, { workspace: owner, timeZone: timeZone, t: t }), _jsx(EmailColumn, { workspace: agent, timeZone: timeZone, t: t })] }) })] }));
1041
+ }