@elizaos/ui 2.0.0-alpha.382 → 2.0.0-alpha.385

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 (777) hide show
  1. package/apps/app-companion/src/components/avatar/VrmViewer.d.ts.map +1 -1
  2. package/apps/app-companion/src/components/avatar/VrmViewer.js +2 -1
  3. package/apps/app-companion/src/components/companion/CompanionAppView.d.ts.map +1 -1
  4. package/apps/app-companion/src/components/companion/CompanionAppView.js +2 -1
  5. package/apps/app-companion/src/components/companion/CompanionView.d.ts.map +1 -1
  6. package/apps/app-companion/src/components/companion/CompanionView.js +2 -1
  7. package/apps/app-companion/src/components/companion/EmotePicker.d.ts.map +1 -1
  8. package/apps/app-companion/src/components/companion/EmotePicker.js +1 -1
  9. package/apps/app-companion/src/components/companion/scene-overlay-bridge.d.ts.map +1 -1
  10. package/apps/app-companion/src/components/companion/scene-overlay-bridge.js +2 -1
  11. package/apps/app-companion/src/index.d.ts +3 -3
  12. package/apps/app-companion/src/index.d.ts.map +1 -1
  13. package/apps/app-companion/src/index.js +3 -3
  14. package/apps/app-elizamaker/src/drop-service.d.ts +2 -2
  15. package/apps/app-elizamaker/src/drop-service.d.ts.map +1 -1
  16. package/apps/app-elizamaker/src/twitter-verify.d.ts +2 -2
  17. package/apps/app-elizamaker/src/twitter-verify.d.ts.map +1 -1
  18. package/apps/app-lifeops/src/api/client-lifeops.d.ts +1 -1
  19. package/apps/app-lifeops/src/api/client-lifeops.d.ts.map +1 -1
  20. package/apps/app-lifeops/src/contracts/index.d.ts +1 -1
  21. package/apps/app-lifeops/src/contracts/index.d.ts.map +1 -1
  22. package/apps/app-lifeops/src/contracts/index.js +1 -1
  23. package/apps/app-lifeops/src/inbox/message-fetcher.d.ts.map +1 -1
  24. package/apps/app-lifeops/src/inbox/message-fetcher.js +4 -2
  25. package/apps/app-lifeops/src/lifeops/google-managed-client.d.ts.map +1 -1
  26. package/apps/app-lifeops/src/lifeops/google-managed-client.js +4 -3
  27. package/apps/app-lifeops/src/lifeops/paypal-managed-client.d.ts.map +1 -1
  28. package/apps/app-lifeops/src/lifeops/paypal-managed-client.js +4 -3
  29. package/apps/app-lifeops/src/lifeops/plaid-managed-client.d.ts.map +1 -1
  30. package/apps/app-lifeops/src/lifeops/plaid-managed-client.js +4 -3
  31. package/apps/app-lifeops/src/lifeops/repository.d.ts +12 -1
  32. package/apps/app-lifeops/src/lifeops/repository.d.ts.map +1 -1
  33. package/apps/app-lifeops/src/lifeops/repository.js +135 -0
  34. package/apps/app-lifeops/src/lifeops/schedule-sync-client.js +1 -1
  35. package/apps/app-lifeops/src/lifeops/schema.d.ts +4587 -3791
  36. package/apps/app-lifeops/src/lifeops/schema.d.ts.map +1 -1
  37. package/apps/app-lifeops/src/lifeops/schema.js +30 -0
  38. package/apps/app-lifeops/src/lifeops/service-mixin-inbox.d.ts +2 -0
  39. package/apps/app-lifeops/src/lifeops/service-mixin-inbox.d.ts.map +1 -1
  40. package/apps/app-lifeops/src/lifeops/service-mixin-inbox.js +103 -13
  41. package/apps/app-lifeops/src/routes/cloud-features-routes.d.ts.map +1 -1
  42. package/apps/app-lifeops/src/routes/cloud-features-routes.js +2 -1
  43. package/apps/app-lifeops/src/routes/travel-provider-relay-routes.d.ts.map +1 -1
  44. package/apps/app-lifeops/src/routes/travel-provider-relay-routes.js +2 -1
  45. package/package.json +1 -1
  46. package/packages/agent/src/actions/grounded-action-reply.d.ts.map +1 -1
  47. package/packages/agent/src/actions/grounded-action-reply.js +1 -1
  48. package/packages/agent/src/actions/index.d.ts +1 -0
  49. package/packages/agent/src/actions/index.d.ts.map +1 -1
  50. package/packages/agent/src/actions/index.js +1 -0
  51. package/packages/agent/src/actions/scratchpad.d.ts +7 -0
  52. package/packages/agent/src/actions/scratchpad.d.ts.map +1 -0
  53. package/packages/agent/src/actions/scratchpad.js +394 -0
  54. package/packages/agent/src/actions/settings-actions.js +1 -1
  55. package/packages/agent/src/actions/terminal.d.ts.map +1 -1
  56. package/packages/agent/src/actions/terminal.js +10 -2
  57. package/packages/agent/src/api/apps-routes.d.ts.map +1 -1
  58. package/packages/agent/src/api/apps-routes.js +171 -0
  59. package/packages/agent/src/api/binance-skill-helpers.d.ts.map +1 -1
  60. package/packages/agent/src/api/chat-routes.d.ts +3 -0
  61. package/packages/agent/src/api/chat-routes.d.ts.map +1 -1
  62. package/packages/agent/src/api/chat-routes.js +33 -14
  63. package/packages/agent/src/api/conversation-routes.js +2 -2
  64. package/packages/agent/src/api/misc-routes.d.ts.map +1 -1
  65. package/packages/agent/src/api/misc-routes.js +2 -2
  66. package/packages/agent/src/api/permissions-routes.js +1 -1
  67. package/packages/agent/src/api/plugin-routes.d.ts.map +1 -1
  68. package/packages/agent/src/api/plugin-routes.js +7 -1
  69. package/packages/agent/src/api/provider-switch-config.js +1 -1
  70. package/packages/agent/src/api/registry-service.d.ts +1 -1
  71. package/packages/agent/src/api/registry-service.d.ts.map +1 -1
  72. package/packages/agent/src/api/server-auth.d.ts.map +1 -1
  73. package/packages/agent/src/api/server-auth.js +119 -1
  74. package/packages/agent/src/api/server-helpers-auth.d.ts.map +1 -1
  75. package/packages/agent/src/api/server-helpers-auth.js +119 -1
  76. package/packages/agent/src/api/server-helpers-swarm.d.ts +1 -1
  77. package/packages/agent/src/api/server-helpers-swarm.d.ts.map +1 -1
  78. package/packages/agent/src/api/server-helpers.js +1 -1
  79. package/packages/agent/src/api/server-types.d.ts +2 -2
  80. package/packages/agent/src/api/server-types.d.ts.map +1 -1
  81. package/packages/agent/src/api/server.d.ts.map +1 -1
  82. package/packages/agent/src/api/server.js +5 -4
  83. package/packages/agent/src/api/training-backend-check.d.ts +1 -1
  84. package/packages/agent/src/api/training-backend-check.d.ts.map +1 -1
  85. package/packages/agent/src/api/training-backend-check.js +1 -1
  86. package/packages/agent/src/api/training-routes.d.ts +1 -1
  87. package/packages/agent/src/api/training-routes.d.ts.map +1 -1
  88. package/packages/agent/src/api/training-routes.js +1 -1
  89. package/packages/agent/src/api/training-service-like.d.ts +1 -1
  90. package/packages/agent/src/api/training-service-like.d.ts.map +1 -1
  91. package/packages/agent/src/api/trajectory-routes.d.ts +1 -1
  92. package/packages/agent/src/api/trajectory-routes.d.ts.map +1 -1
  93. package/packages/agent/src/api/trajectory-routes.js +1 -1
  94. package/packages/agent/src/api/wallet-capability.js +1 -1
  95. package/packages/agent/src/api/wallet-evm-balance.js +1 -1
  96. package/packages/agent/src/api/wallet.d.ts +1 -1
  97. package/packages/agent/src/api/wallet.d.ts.map +1 -1
  98. package/packages/agent/src/api/wallet.js +2 -2
  99. package/packages/agent/src/awareness/index.d.ts +2 -0
  100. package/packages/agent/src/awareness/index.d.ts.map +1 -0
  101. package/packages/agent/src/awareness/index.js +1 -0
  102. package/packages/agent/src/config/config.d.ts.map +1 -1
  103. package/packages/agent/src/config/config.js +2 -0
  104. package/packages/agent/src/config/index.d.ts +1 -0
  105. package/packages/agent/src/config/index.d.ts.map +1 -1
  106. package/packages/agent/src/config/index.js +1 -0
  107. package/packages/agent/src/config/model-metadata.d.ts +20 -0
  108. package/packages/agent/src/config/model-metadata.d.ts.map +1 -0
  109. package/packages/agent/src/config/model-metadata.js +133 -0
  110. package/packages/agent/src/config/zod-schema.core.d.ts +28 -28
  111. package/packages/agent/src/config/zod-schema.core.d.ts.map +1 -1
  112. package/packages/agent/src/config/zod-schema.core.js +16 -9
  113. package/packages/agent/src/config/zod-schema.d.ts +10 -10
  114. package/packages/agent/src/index.d.ts +6 -11
  115. package/packages/agent/src/index.d.ts.map +1 -1
  116. package/packages/agent/src/index.js +8 -10
  117. package/packages/agent/src/providers/media-provider.js +1 -1
  118. package/packages/agent/src/runtime/custom-actions.d.ts.map +1 -1
  119. package/packages/agent/src/runtime/custom-actions.js +1 -1
  120. package/packages/agent/src/runtime/eliza-plugin.d.ts.map +1 -1
  121. package/packages/agent/src/runtime/eliza-plugin.js +6 -0
  122. package/packages/agent/src/runtime/eliza.d.ts.map +1 -1
  123. package/packages/agent/src/runtime/eliza.js +7 -7
  124. package/packages/agent/src/runtime/prompt-optimization.d.ts +24 -1
  125. package/packages/agent/src/runtime/prompt-optimization.d.ts.map +1 -1
  126. package/packages/agent/src/runtime/prompt-optimization.js +292 -27
  127. package/packages/agent/src/runtime/trajectory-internals.d.ts +1 -0
  128. package/packages/agent/src/runtime/trajectory-internals.d.ts.map +1 -1
  129. package/packages/agent/src/runtime/trajectory-storage.d.ts.map +1 -1
  130. package/packages/agent/src/runtime/trajectory-storage.js +3 -0
  131. package/packages/agent/src/services/index.d.ts +4 -4
  132. package/packages/agent/src/services/index.d.ts.map +1 -1
  133. package/packages/agent/src/services/index.js +2 -2
  134. package/packages/agent/src/services/registry-client-app-meta.d.ts.map +1 -1
  135. package/packages/agent/src/services/registry-client-app-meta.js +0 -61
  136. package/packages/agent/src/services/skill-marketplace.d.ts.map +1 -1
  137. package/packages/app-core/src/App.js +1 -1
  138. package/packages/app-core/src/api/auth.js +1 -1
  139. package/packages/app-core/src/api/client-agent.d.ts +1 -2
  140. package/packages/app-core/src/api/client-agent.d.ts.map +1 -1
  141. package/packages/app-core/src/api/client-chat.d.ts +10 -1
  142. package/packages/app-core/src/api/client-chat.d.ts.map +1 -1
  143. package/packages/app-core/src/api/client-chat.js +33 -0
  144. package/packages/app-core/src/api/client-skills.d.ts.map +1 -1
  145. package/packages/app-core/src/api/client-types-chat.d.ts +1 -0
  146. package/packages/app-core/src/api/client-types-chat.d.ts.map +1 -1
  147. package/packages/app-core/src/api/client-types-config.d.ts +2 -2
  148. package/packages/app-core/src/api/client-types-config.d.ts.map +1 -1
  149. package/packages/app-core/src/api/client-wallet.d.ts +2 -4
  150. package/packages/app-core/src/api/client-wallet.d.ts.map +1 -1
  151. package/packages/app-core/src/api/client.d.ts +3 -4
  152. package/packages/app-core/src/api/client.d.ts.map +1 -1
  153. package/packages/app-core/src/api/client.js +1 -1
  154. package/packages/app-core/src/api/compat-route-shared.d.ts +1 -1
  155. package/packages/app-core/src/api/compat-route-shared.d.ts.map +1 -1
  156. package/packages/app-core/src/api/compat-route-shared.js +117 -1
  157. package/packages/app-core/src/api/server-cloud-tts.js +1 -1
  158. package/packages/app-core/src/api/trusted-local-request.d.ts +4 -0
  159. package/packages/app-core/src/api/trusted-local-request.d.ts.map +1 -0
  160. package/packages/app-core/src/api/trusted-local-request.js +176 -0
  161. package/packages/app-core/src/autonomy/index.d.ts.map +1 -1
  162. package/packages/app-core/src/autonomy/index.js +3 -1
  163. package/packages/app-core/src/components/auth/LoginView.d.ts +3 -23
  164. package/packages/app-core/src/components/auth/LoginView.d.ts.map +1 -1
  165. package/packages/app-core/src/components/auth/LoginView.js +43 -33
  166. package/packages/app-core/src/components/chat/AppsSection.d.ts.map +1 -1
  167. package/packages/app-core/src/components/chat/AppsSection.js +61 -6
  168. package/packages/app-core/src/components/chat/MessageContent.d.ts.map +1 -1
  169. package/packages/app-core/src/components/chat/MessageContent.js +26 -3
  170. package/packages/app-core/src/components/chat/message-choice-parser.d.ts +20 -0
  171. package/packages/app-core/src/components/chat/message-choice-parser.d.ts.map +1 -0
  172. package/packages/app-core/src/components/chat/message-choice-parser.js +53 -0
  173. package/packages/app-core/src/components/chat/widgets/ChoiceWidget.d.ts +24 -0
  174. package/packages/app-core/src/components/chat/widgets/ChoiceWidget.d.ts.map +1 -0
  175. package/packages/app-core/src/components/chat/widgets/ChoiceWidget.js +38 -0
  176. package/packages/app-core/src/components/connectors/ConnectorSetupPanel.js +1 -1
  177. package/packages/app-core/src/components/custom-actions/CustomActionEditor.d.ts.map +1 -1
  178. package/packages/app-core/src/components/custom-actions/CustomActionsPanel.d.ts.map +1 -1
  179. package/packages/app-core/src/components/custom-actions/CustomActionsView.d.ts.map +1 -1
  180. package/packages/app-core/src/components/custom-actions/custom-action-form.d.ts.map +1 -1
  181. package/packages/app-core/src/components/pages/BrowserWorkspaceView.js +1 -1
  182. package/packages/app-core/src/components/pages/KnowledgeView.d.ts.map +1 -1
  183. package/packages/app-core/src/components/pages/KnowledgeView.js +11 -1
  184. package/packages/app-core/src/components/pages/PluginConfigForm.d.ts.map +1 -1
  185. package/packages/app-core/src/components/pages/PluginConfigForm.js +1 -1
  186. package/packages/app-core/src/components/pages/ScratchpadView.d.ts +2 -0
  187. package/packages/app-core/src/components/pages/ScratchpadView.d.ts.map +1 -0
  188. package/packages/app-core/src/components/pages/ScratchpadView.js +364 -0
  189. package/packages/app-core/src/components/pages/SettingsView.d.ts.map +1 -1
  190. package/packages/app-core/src/components/pages/SettingsView.js +29 -5
  191. package/packages/app-core/src/components/pages/VectorBrowserView.d.ts.map +1 -1
  192. package/packages/app-core/src/components/pages/VectorBrowserView.js +1 -1
  193. package/packages/app-core/src/components/pages/config-page-sections.d.ts +1 -1
  194. package/packages/app-core/src/components/pages/config-page-sections.d.ts.map +1 -1
  195. package/packages/app-core/src/components/pages/config-page-sections.js +1 -1
  196. package/packages/app-core/src/components/pages/plugin-list-utils.d.ts +1 -1
  197. package/packages/app-core/src/components/pages/plugin-list-utils.d.ts.map +1 -1
  198. package/packages/app-core/src/components/pages/useBrowserWorkspaceWalletBridge.d.ts +1 -1
  199. package/packages/app-core/src/components/pages/useBrowserWorkspaceWalletBridge.d.ts.map +1 -1
  200. package/packages/app-core/src/components/pages/useBrowserWorkspaceWalletBridge.js +1 -1
  201. package/packages/app-core/src/components/settings/ApiKeyConfig.js +1 -1
  202. package/packages/app-core/src/components/settings/AppearanceSettingsSection.d.ts.map +1 -1
  203. package/packages/app-core/src/components/settings/AppearanceSettingsSection.js +1 -1
  204. package/packages/app-core/src/components/settings/AppsManagementSection.d.ts +12 -0
  205. package/packages/app-core/src/components/settings/AppsManagementSection.d.ts.map +1 -0
  206. package/packages/app-core/src/components/settings/AppsManagementSection.js +285 -0
  207. package/packages/app-core/src/components/settings/PermissionsSection.js +1 -1
  208. package/packages/app-core/src/components/settings/ProviderSwitcher.d.ts.map +1 -1
  209. package/packages/app-core/src/components/settings/ProviderSwitcher.js +2 -2
  210. package/packages/app-core/src/components/settings/SecuritySettingsSection.d.ts.map +1 -1
  211. package/packages/app-core/src/components/settings/SecuritySettingsSection.js +150 -33
  212. package/packages/app-core/src/components/settings/cloud-model-schema.d.ts +1 -1
  213. package/packages/app-core/src/components/settings/cloud-model-schema.d.ts.map +1 -1
  214. package/packages/app-core/src/components/shell/Header.d.ts.map +1 -1
  215. package/packages/app-core/src/components/shell/Header.js +28 -1
  216. package/packages/app-core/src/components/steward/injected.d.ts.map +1 -1
  217. package/packages/app-core/src/components/steward/injected.js +1 -1
  218. package/packages/app-core/src/components/training/injected.d.ts.map +1 -1
  219. package/packages/app-core/src/components/training/injected.js +1 -1
  220. package/packages/app-core/src/config/boot-config-store.d.ts +1 -1
  221. package/packages/app-core/src/config/boot-config-store.d.ts.map +1 -1
  222. package/packages/app-core/src/content-packs/bundled-packs.d.ts.map +1 -1
  223. package/packages/app-core/src/hooks/index.d.ts +0 -2
  224. package/packages/app-core/src/hooks/index.d.ts.map +1 -1
  225. package/packages/app-core/src/hooks/index.js +0 -2
  226. package/packages/app-core/src/hooks/useAuthStatus.d.ts +5 -0
  227. package/packages/app-core/src/hooks/useAuthStatus.d.ts.map +1 -1
  228. package/packages/app-core/src/hooks/useAuthStatus.js +41 -18
  229. package/packages/app-core/src/hooks/useSignalPairing.d.ts +1 -1
  230. package/packages/app-core/src/hooks/useSignalPairing.d.ts.map +1 -1
  231. package/packages/app-core/src/hooks/useWhatsAppPairing.d.ts +1 -1
  232. package/packages/app-core/src/hooks/useWhatsAppPairing.d.ts.map +1 -1
  233. package/packages/app-core/src/i18n/locales/en.json +0 -1
  234. package/packages/app-core/src/i18n/locales/es.json +0 -1
  235. package/packages/app-core/src/i18n/locales/ko.json +0 -1
  236. package/packages/app-core/src/i18n/locales/pt.json +0 -1
  237. package/packages/app-core/src/i18n/locales/tl.json +0 -1
  238. package/packages/app-core/src/i18n/locales/vi.json +0 -1
  239. package/packages/app-core/src/i18n/locales/zh-CN.json +0 -1
  240. package/packages/app-core/src/index.d.ts +0 -1
  241. package/packages/app-core/src/index.d.ts.map +1 -1
  242. package/packages/app-core/src/index.js +0 -1
  243. package/packages/app-core/src/runtime/channel-plugin-map.d.ts.map +1 -1
  244. package/packages/app-core/src/runtime/channel-plugin-map.js +1 -1
  245. package/packages/app-core/src/runtime/plugin-manager-guard.d.ts.map +1 -1
  246. package/packages/app-core/src/runtime/plugin-manager-guard.js +1 -1
  247. package/packages/app-core/src/services/plugin-installer.d.ts.map +1 -1
  248. package/packages/app-core/src/services/plugin-installer.js +1 -8
  249. package/packages/app-core/src/state/index.d.ts +0 -1
  250. package/packages/app-core/src/state/index.d.ts.map +1 -1
  251. package/packages/app-core/src/state/index.js +0 -1
  252. package/packages/app-core/src/state/startup-phase-restore.d.ts.map +1 -1
  253. package/packages/app-core/src/state/startup-phase-restore.js +1 -1
  254. package/packages/app-core/src/state/useOnboardingState.js +2 -2
  255. package/packages/app-core/src/state/usePluginsSkillsState.d.ts +4 -4
  256. package/packages/app-core/src/types/index.d.ts +1 -1
  257. package/packages/app-core/src/types/index.d.ts.map +1 -1
  258. package/packages/shared/src/contracts/index.d.ts +1 -0
  259. package/packages/shared/src/contracts/index.d.ts.map +1 -1
  260. package/packages/shared/src/contracts/index.js +1 -0
  261. package/packages/shared/src/contracts/scratchpad.d.ts +136 -0
  262. package/packages/shared/src/contracts/scratchpad.d.ts.map +1 -0
  263. package/packages/shared/src/contracts/scratchpad.js +90 -0
  264. package/packages/shared/src/index.d.ts +13 -13
  265. package/packages/shared/src/index.d.ts.map +1 -1
  266. package/packages/shared/src/index.js +19 -19
  267. package/packages/shared/src/spoken-text.js +1 -1
  268. package/packages/typescript/src/features/advanced-capabilities/evaluators/factExtractor.d.ts.map +1 -1
  269. package/packages/typescript/src/features/advanced-capabilities/evaluators/factExtractor.js +12 -6
  270. package/packages/typescript/src/generated/action-docs.d.ts +25 -0
  271. package/packages/typescript/src/generated/action-docs.d.ts.map +1 -1
  272. package/packages/typescript/src/generated/action-docs.js +51 -0
  273. package/packages/typescript/src/services/message.d.ts.map +1 -1
  274. package/packages/typescript/src/services/message.js +1 -3
  275. package/packages/typescript/src/types/tools.d.ts.map +1 -1
  276. package/packages/typescript/src/types/tools.js +7 -3
  277. package/apps/app-lifeops/src/action.d.ts +0 -3
  278. package/apps/app-lifeops/src/action.d.ts.map +0 -1
  279. package/apps/app-lifeops/src/action.js +0 -351
  280. package/apps/app-lifeops/src/actions/activity-report.d.ts +0 -13
  281. package/apps/app-lifeops/src/actions/activity-report.d.ts.map +0 -1
  282. package/apps/app-lifeops/src/actions/activity-report.js +0 -313
  283. package/apps/app-lifeops/src/actions/app-blocker.d.ts +0 -7
  284. package/apps/app-lifeops/src/actions/app-blocker.d.ts.map +0 -1
  285. package/apps/app-lifeops/src/actions/app-blocker.js +0 -454
  286. package/apps/app-lifeops/src/actions/approval.d.ts +0 -21
  287. package/apps/app-lifeops/src/actions/approval.d.ts.map +0 -1
  288. package/apps/app-lifeops/src/actions/approval.js +0 -342
  289. package/apps/app-lifeops/src/actions/autofill.d.ts +0 -35
  290. package/apps/app-lifeops/src/actions/autofill.d.ts.map +0 -1
  291. package/apps/app-lifeops/src/actions/autofill.js +0 -475
  292. package/apps/app-lifeops/src/actions/book-travel-executor.d.ts +0 -9
  293. package/apps/app-lifeops/src/actions/book-travel-executor.d.ts.map +0 -1
  294. package/apps/app-lifeops/src/actions/book-travel-executor.js +0 -65
  295. package/apps/app-lifeops/src/actions/book-travel.d.ts +0 -5
  296. package/apps/app-lifeops/src/actions/book-travel.d.ts.map +0 -1
  297. package/apps/app-lifeops/src/actions/book-travel.js +0 -491
  298. package/apps/app-lifeops/src/actions/calendar.d.ts +0 -19
  299. package/apps/app-lifeops/src/actions/calendar.d.ts.map +0 -1
  300. package/apps/app-lifeops/src/actions/calendar.js +0 -3189
  301. package/apps/app-lifeops/src/actions/calendly.d.ts +0 -3
  302. package/apps/app-lifeops/src/actions/calendly.d.ts.map +0 -1
  303. package/apps/app-lifeops/src/actions/calendly.js +0 -285
  304. package/apps/app-lifeops/src/actions/chat-thread-control.d.ts +0 -3
  305. package/apps/app-lifeops/src/actions/chat-thread-control.d.ts.map +0 -1
  306. package/apps/app-lifeops/src/actions/chat-thread-control.js +0 -260
  307. package/apps/app-lifeops/src/actions/checkin.d.ts +0 -8
  308. package/apps/app-lifeops/src/actions/checkin.d.ts.map +0 -1
  309. package/apps/app-lifeops/src/actions/checkin.js +0 -230
  310. package/apps/app-lifeops/src/actions/computer-use.d.ts +0 -14
  311. package/apps/app-lifeops/src/actions/computer-use.d.ts.map +0 -1
  312. package/apps/app-lifeops/src/actions/computer-use.js +0 -365
  313. package/apps/app-lifeops/src/actions/cross-channel-send.d.ts +0 -34
  314. package/apps/app-lifeops/src/actions/cross-channel-send.d.ts.map +0 -1
  315. package/apps/app-lifeops/src/actions/cross-channel-send.js +0 -964
  316. package/apps/app-lifeops/src/actions/device-bus.d.ts +0 -19
  317. package/apps/app-lifeops/src/actions/device-bus.d.ts.map +0 -1
  318. package/apps/app-lifeops/src/actions/device-bus.js +0 -386
  319. package/apps/app-lifeops/src/actions/dossier.d.ts +0 -5
  320. package/apps/app-lifeops/src/actions/dossier.d.ts.map +0 -1
  321. package/apps/app-lifeops/src/actions/dossier.js +0 -227
  322. package/apps/app-lifeops/src/actions/email-unsubscribe.d.ts +0 -5
  323. package/apps/app-lifeops/src/actions/email-unsubscribe.d.ts.map +0 -1
  324. package/apps/app-lifeops/src/actions/email-unsubscribe.js +0 -172
  325. package/apps/app-lifeops/src/actions/gmail.d.ts +0 -57
  326. package/apps/app-lifeops/src/actions/gmail.d.ts.map +0 -1
  327. package/apps/app-lifeops/src/actions/gmail.js +0 -2540
  328. package/apps/app-lifeops/src/actions/health.d.ts +0 -9
  329. package/apps/app-lifeops/src/actions/health.d.ts.map +0 -1
  330. package/apps/app-lifeops/src/actions/health.js +0 -398
  331. package/apps/app-lifeops/src/actions/inbox.d.ts +0 -5
  332. package/apps/app-lifeops/src/actions/inbox.d.ts.map +0 -1
  333. package/apps/app-lifeops/src/actions/inbox.js +0 -1244
  334. package/apps/app-lifeops/src/actions/intent-sync.d.ts +0 -5
  335. package/apps/app-lifeops/src/actions/intent-sync.d.ts.map +0 -1
  336. package/apps/app-lifeops/src/actions/intent-sync.js +0 -326
  337. package/apps/app-lifeops/src/actions/life-goal-extractor.d.ts +0 -69
  338. package/apps/app-lifeops/src/actions/life-goal-extractor.d.ts.map +0 -1
  339. package/apps/app-lifeops/src/actions/life-goal-extractor.js +0 -420
  340. package/apps/app-lifeops/src/actions/life-param-extractor.d.ts +0 -78
  341. package/apps/app-lifeops/src/actions/life-param-extractor.d.ts.map +0 -1
  342. package/apps/app-lifeops/src/actions/life-param-extractor.js +0 -431
  343. package/apps/app-lifeops/src/actions/life-recent-context.d.ts +0 -9
  344. package/apps/app-lifeops/src/actions/life-recent-context.d.ts.map +0 -1
  345. package/apps/app-lifeops/src/actions/life-recent-context.js +0 -78
  346. package/apps/app-lifeops/src/actions/life-update-extractor.d.ts +0 -27
  347. package/apps/app-lifeops/src/actions/life-update-extractor.d.ts.map +0 -1
  348. package/apps/app-lifeops/src/actions/life-update-extractor.js +0 -195
  349. package/apps/app-lifeops/src/actions/life.d.ts +0 -5
  350. package/apps/app-lifeops/src/actions/life.d.ts.map +0 -1
  351. package/apps/app-lifeops/src/actions/life.extractor.d.ts +0 -18
  352. package/apps/app-lifeops/src/actions/life.extractor.d.ts.map +0 -1
  353. package/apps/app-lifeops/src/actions/life.extractor.js +0 -363
  354. package/apps/app-lifeops/src/actions/life.js +0 -3247
  355. package/apps/app-lifeops/src/actions/lifeops-connector.d.ts +0 -5
  356. package/apps/app-lifeops/src/actions/lifeops-connector.d.ts.map +0 -1
  357. package/apps/app-lifeops/src/actions/lifeops-connector.js +0 -683
  358. package/apps/app-lifeops/src/actions/lifeops-extraction-config.d.ts +0 -16
  359. package/apps/app-lifeops/src/actions/lifeops-extraction-config.d.ts.map +0 -1
  360. package/apps/app-lifeops/src/actions/lifeops-extraction-config.js +0 -25
  361. package/apps/app-lifeops/src/actions/lifeops-google-helpers.d.ts +0 -64
  362. package/apps/app-lifeops/src/actions/lifeops-google-helpers.d.ts.map +0 -1
  363. package/apps/app-lifeops/src/actions/lifeops-google-helpers.js +0 -671
  364. package/apps/app-lifeops/src/actions/lifeops-mutate.d.ts +0 -5
  365. package/apps/app-lifeops/src/actions/lifeops-mutate.d.ts.map +0 -1
  366. package/apps/app-lifeops/src/actions/lifeops-mutate.js +0 -769
  367. package/apps/app-lifeops/src/actions/list-remote-sessions.d.ts +0 -6
  368. package/apps/app-lifeops/src/actions/list-remote-sessions.d.ts.map +0 -1
  369. package/apps/app-lifeops/src/actions/list-remote-sessions.js +0 -45
  370. package/apps/app-lifeops/src/actions/non-actionable-request.d.ts +0 -17
  371. package/apps/app-lifeops/src/actions/non-actionable-request.d.ts.map +0 -1
  372. package/apps/app-lifeops/src/actions/non-actionable-request.js +0 -25
  373. package/apps/app-lifeops/src/actions/owner-app-block.d.ts +0 -12
  374. package/apps/app-lifeops/src/actions/owner-app-block.d.ts.map +0 -1
  375. package/apps/app-lifeops/src/actions/owner-app-block.js +0 -144
  376. package/apps/app-lifeops/src/actions/owner-calendar.d.ts +0 -15
  377. package/apps/app-lifeops/src/actions/owner-calendar.d.ts.map +0 -1
  378. package/apps/app-lifeops/src/actions/owner-calendar.js +0 -762
  379. package/apps/app-lifeops/src/actions/owner-inbox.d.ts +0 -5
  380. package/apps/app-lifeops/src/actions/owner-inbox.d.ts.map +0 -1
  381. package/apps/app-lifeops/src/actions/owner-inbox.js +0 -662
  382. package/apps/app-lifeops/src/actions/owner-remote-desktop.d.ts +0 -12
  383. package/apps/app-lifeops/src/actions/owner-remote-desktop.d.ts.map +0 -1
  384. package/apps/app-lifeops/src/actions/owner-remote-desktop.js +0 -173
  385. package/apps/app-lifeops/src/actions/owner-schedule.d.ts +0 -3
  386. package/apps/app-lifeops/src/actions/owner-schedule.d.ts.map +0 -1
  387. package/apps/app-lifeops/src/actions/owner-schedule.js +0 -174
  388. package/apps/app-lifeops/src/actions/owner-screen-time.d.ts +0 -10
  389. package/apps/app-lifeops/src/actions/owner-screen-time.d.ts.map +0 -1
  390. package/apps/app-lifeops/src/actions/owner-screen-time.js +0 -213
  391. package/apps/app-lifeops/src/actions/owner-website-block.d.ts +0 -12
  392. package/apps/app-lifeops/src/actions/owner-website-block.d.ts.map +0 -1
  393. package/apps/app-lifeops/src/actions/owner-website-block.js +0 -424
  394. package/apps/app-lifeops/src/actions/password-manager.d.ts +0 -5
  395. package/apps/app-lifeops/src/actions/password-manager.d.ts.map +0 -1
  396. package/apps/app-lifeops/src/actions/password-manager.js +0 -217
  397. package/apps/app-lifeops/src/actions/payments.d.ts +0 -5
  398. package/apps/app-lifeops/src/actions/payments.d.ts.map +0 -1
  399. package/apps/app-lifeops/src/actions/payments.js +0 -236
  400. package/apps/app-lifeops/src/actions/relationships.d.ts +0 -12
  401. package/apps/app-lifeops/src/actions/relationships.d.ts.map +0 -1
  402. package/apps/app-lifeops/src/actions/relationships.js +0 -880
  403. package/apps/app-lifeops/src/actions/remote-desktop.d.ts +0 -5
  404. package/apps/app-lifeops/src/actions/remote-desktop.d.ts.map +0 -1
  405. package/apps/app-lifeops/src/actions/remote-desktop.js +0 -248
  406. package/apps/app-lifeops/src/actions/revoke-remote-session.d.ts +0 -6
  407. package/apps/app-lifeops/src/actions/revoke-remote-session.d.ts.map +0 -1
  408. package/apps/app-lifeops/src/actions/revoke-remote-session.js +0 -73
  409. package/apps/app-lifeops/src/actions/schedule-x-dm-reply.d.ts +0 -3
  410. package/apps/app-lifeops/src/actions/schedule-x-dm-reply.d.ts.map +0 -1
  411. package/apps/app-lifeops/src/actions/schedule-x-dm-reply.js +0 -134
  412. package/apps/app-lifeops/src/actions/scheduled-trigger-task.d.ts +0 -19
  413. package/apps/app-lifeops/src/actions/scheduled-trigger-task.d.ts.map +0 -1
  414. package/apps/app-lifeops/src/actions/scheduled-trigger-task.js +0 -82
  415. package/apps/app-lifeops/src/actions/scheduling.d.ts +0 -70
  416. package/apps/app-lifeops/src/actions/scheduling.d.ts.map +0 -1
  417. package/apps/app-lifeops/src/actions/scheduling.js +0 -1078
  418. package/apps/app-lifeops/src/actions/screen-time.d.ts +0 -8
  419. package/apps/app-lifeops/src/actions/screen-time.d.ts.map +0 -1
  420. package/apps/app-lifeops/src/actions/screen-time.js +0 -249
  421. package/apps/app-lifeops/src/actions/search-across-channels.d.ts +0 -13
  422. package/apps/app-lifeops/src/actions/search-across-channels.d.ts.map +0 -1
  423. package/apps/app-lifeops/src/actions/search-across-channels.js +0 -338
  424. package/apps/app-lifeops/src/actions/start-remote-session.d.ts +0 -14
  425. package/apps/app-lifeops/src/actions/start-remote-session.d.ts.map +0 -1
  426. package/apps/app-lifeops/src/actions/start-remote-session.js +0 -139
  427. package/apps/app-lifeops/src/actions/subscriptions.d.ts +0 -5
  428. package/apps/app-lifeops/src/actions/subscriptions.d.ts.map +0 -1
  429. package/apps/app-lifeops/src/actions/subscriptions.js +0 -404
  430. package/apps/app-lifeops/src/actions/timezone-normalization.d.ts +0 -4
  431. package/apps/app-lifeops/src/actions/timezone-normalization.d.ts.map +0 -1
  432. package/apps/app-lifeops/src/actions/timezone-normalization.js +0 -159
  433. package/apps/app-lifeops/src/actions/twilio-call.d.ts +0 -20
  434. package/apps/app-lifeops/src/actions/twilio-call.d.ts.map +0 -1
  435. package/apps/app-lifeops/src/actions/twilio-call.js +0 -853
  436. package/apps/app-lifeops/src/actions/update-owner-profile.d.ts +0 -5
  437. package/apps/app-lifeops/src/actions/update-owner-profile.d.ts.map +0 -1
  438. package/apps/app-lifeops/src/actions/update-owner-profile.js +0 -181
  439. package/apps/app-lifeops/src/actions/x-read.d.ts +0 -5
  440. package/apps/app-lifeops/src/actions/x-read.d.ts.map +0 -1
  441. package/apps/app-lifeops/src/actions/x-read.js +0 -561
  442. package/apps/app-lifeops/src/activity-profile/activity-tracker-service.d.ts +0 -36
  443. package/apps/app-lifeops/src/activity-profile/activity-tracker-service.d.ts.map +0 -1
  444. package/apps/app-lifeops/src/activity-profile/activity-tracker-service.js +0 -160
  445. package/apps/app-lifeops/src/activity-profile/analyzer.d.ts +0 -23
  446. package/apps/app-lifeops/src/activity-profile/analyzer.d.ts.map +0 -1
  447. package/apps/app-lifeops/src/activity-profile/analyzer.js +0 -555
  448. package/apps/app-lifeops/src/activity-profile/presence-signal-bridge-service.d.ts +0 -14
  449. package/apps/app-lifeops/src/activity-profile/presence-signal-bridge-service.d.ts.map +0 -1
  450. package/apps/app-lifeops/src/activity-profile/presence-signal-bridge-service.js +0 -133
  451. package/apps/app-lifeops/src/activity-profile/proactive-planner.d.ts +0 -71
  452. package/apps/app-lifeops/src/activity-profile/proactive-planner.d.ts.map +0 -1
  453. package/apps/app-lifeops/src/activity-profile/proactive-planner.js +0 -567
  454. package/apps/app-lifeops/src/activity-profile/proactive-worker.d.ts +0 -32
  455. package/apps/app-lifeops/src/activity-profile/proactive-worker.d.ts.map +0 -1
  456. package/apps/app-lifeops/src/activity-profile/proactive-worker.js +0 -676
  457. package/apps/app-lifeops/src/activity-profile/service.d.ts +0 -11
  458. package/apps/app-lifeops/src/activity-profile/service.d.ts.map +0 -1
  459. package/apps/app-lifeops/src/activity-profile/service.js +0 -246
  460. package/apps/app-lifeops/src/app-blocker/access.d.ts +0 -8
  461. package/apps/app-lifeops/src/app-blocker/access.d.ts.map +0 -1
  462. package/apps/app-lifeops/src/app-blocker/access.js +0 -35
  463. package/apps/app-lifeops/src/app-blocker/engine.d.ts +0 -10
  464. package/apps/app-lifeops/src/app-blocker/engine.d.ts.map +0 -1
  465. package/apps/app-lifeops/src/app-blocker/engine.js +0 -43
  466. package/apps/app-lifeops/src/components/AppBlockerSettingsCard.d.ts +0 -3
  467. package/apps/app-lifeops/src/components/AppBlockerSettingsCard.d.ts.map +0 -1
  468. package/apps/app-lifeops/src/components/AppBlockerSettingsCard.js +0 -189
  469. package/apps/app-lifeops/src/components/BrowserBridgeSetupPanel.d.ts +0 -2
  470. package/apps/app-lifeops/src/components/BrowserBridgeSetupPanel.d.ts.map +0 -1
  471. package/apps/app-lifeops/src/components/BrowserBridgeSetupPanel.js +0 -1065
  472. package/apps/app-lifeops/src/components/BrowserBridgeStatusChip.d.ts +0 -7
  473. package/apps/app-lifeops/src/components/BrowserBridgeStatusChip.d.ts.map +0 -1
  474. package/apps/app-lifeops/src/components/BrowserBridgeStatusChip.js +0 -74
  475. package/apps/app-lifeops/src/components/DataSourcesStrip.d.ts +0 -14
  476. package/apps/app-lifeops/src/components/DataSourcesStrip.d.ts.map +0 -1
  477. package/apps/app-lifeops/src/components/DataSourcesStrip.js +0 -36
  478. package/apps/app-lifeops/src/components/EventEditorDrawer.d.ts +0 -23
  479. package/apps/app-lifeops/src/components/EventEditorDrawer.d.ts.map +0 -1
  480. package/apps/app-lifeops/src/components/EventEditorDrawer.js +0 -514
  481. package/apps/app-lifeops/src/components/LifeOpsActivitySignalsEffect.d.ts +0 -2
  482. package/apps/app-lifeops/src/components/LifeOpsActivitySignalsEffect.d.ts.map +0 -1
  483. package/apps/app-lifeops/src/components/LifeOpsActivitySignalsEffect.js +0 -10
  484. package/apps/app-lifeops/src/components/LifeOpsCalendarSection.d.ts +0 -15
  485. package/apps/app-lifeops/src/components/LifeOpsCalendarSection.d.ts.map +0 -1
  486. package/apps/app-lifeops/src/components/LifeOpsCalendarSection.js +0 -515
  487. package/apps/app-lifeops/src/components/LifeOpsChatAdapter.d.ts +0 -34
  488. package/apps/app-lifeops/src/components/LifeOpsChatAdapter.d.ts.map +0 -1
  489. package/apps/app-lifeops/src/components/LifeOpsChatAdapter.js +0 -175
  490. package/apps/app-lifeops/src/components/LifeOpsFeatureTogglesSection.d.ts +0 -2
  491. package/apps/app-lifeops/src/components/LifeOpsFeatureTogglesSection.d.ts.map +0 -1
  492. package/apps/app-lifeops/src/components/LifeOpsFeatureTogglesSection.js +0 -99
  493. package/apps/app-lifeops/src/components/LifeOpsHabitVisuals.d.ts +0 -37
  494. package/apps/app-lifeops/src/components/LifeOpsHabitVisuals.d.ts.map +0 -1
  495. package/apps/app-lifeops/src/components/LifeOpsHabitVisuals.js +0 -88
  496. package/apps/app-lifeops/src/components/LifeOpsInboxSection.d.ts +0 -13
  497. package/apps/app-lifeops/src/components/LifeOpsInboxSection.d.ts.map +0 -1
  498. package/apps/app-lifeops/src/components/LifeOpsInboxSection.js +0 -490
  499. package/apps/app-lifeops/src/components/LifeOpsLinkBankButton.d.ts +0 -12
  500. package/apps/app-lifeops/src/components/LifeOpsLinkBankButton.d.ts.map +0 -1
  501. package/apps/app-lifeops/src/components/LifeOpsLinkBankButton.js +0 -92
  502. package/apps/app-lifeops/src/components/LifeOpsLinkPaypalButton.d.ts +0 -12
  503. package/apps/app-lifeops/src/components/LifeOpsLinkPaypalButton.d.ts.map +0 -1
  504. package/apps/app-lifeops/src/components/LifeOpsLinkPaypalButton.js +0 -160
  505. package/apps/app-lifeops/src/components/LifeOpsMoneySection.d.ts +0 -3
  506. package/apps/app-lifeops/src/components/LifeOpsMoneySection.d.ts.map +0 -1
  507. package/apps/app-lifeops/src/components/LifeOpsMoneySection.js +0 -373
  508. package/apps/app-lifeops/src/components/LifeOpsNavRail.d.ts +0 -9
  509. package/apps/app-lifeops/src/components/LifeOpsNavRail.d.ts.map +0 -1
  510. package/apps/app-lifeops/src/components/LifeOpsNavRail.js +0 -93
  511. package/apps/app-lifeops/src/components/LifeOpsOperationalPanels.d.ts +0 -4
  512. package/apps/app-lifeops/src/components/LifeOpsOperationalPanels.d.ts.map +0 -1
  513. package/apps/app-lifeops/src/components/LifeOpsOperationalPanels.js +0 -274
  514. package/apps/app-lifeops/src/components/LifeOpsOverviewSection.d.ts +0 -7
  515. package/apps/app-lifeops/src/components/LifeOpsOverviewSection.d.ts.map +0 -1
  516. package/apps/app-lifeops/src/components/LifeOpsOverviewSection.js +0 -670
  517. package/apps/app-lifeops/src/components/LifeOpsPageSections.d.ts +0 -42
  518. package/apps/app-lifeops/src/components/LifeOpsPageSections.d.ts.map +0 -1
  519. package/apps/app-lifeops/src/components/LifeOpsPageSections.js +0 -166
  520. package/apps/app-lifeops/src/components/LifeOpsPageView.d.ts +0 -2
  521. package/apps/app-lifeops/src/components/LifeOpsPageView.d.ts.map +0 -1
  522. package/apps/app-lifeops/src/components/LifeOpsPageView.js +0 -565
  523. package/apps/app-lifeops/src/components/LifeOpsRemindersSection.d.ts +0 -2
  524. package/apps/app-lifeops/src/components/LifeOpsRemindersSection.d.ts.map +0 -1
  525. package/apps/app-lifeops/src/components/LifeOpsRemindersSection.js +0 -749
  526. package/apps/app-lifeops/src/components/LifeOpsResizableSidebar.d.ts +0 -27
  527. package/apps/app-lifeops/src/components/LifeOpsResizableSidebar.d.ts.map +0 -1
  528. package/apps/app-lifeops/src/components/LifeOpsResizableSidebar.js +0 -106
  529. package/apps/app-lifeops/src/components/LifeOpsScreenTimeSection.d.ts +0 -2
  530. package/apps/app-lifeops/src/components/LifeOpsScreenTimeSection.d.ts.map +0 -1
  531. package/apps/app-lifeops/src/components/LifeOpsScreenTimeSection.js +0 -373
  532. package/apps/app-lifeops/src/components/LifeOpsSectionContent.d.ts +0 -10
  533. package/apps/app-lifeops/src/components/LifeOpsSectionContent.d.ts.map +0 -1
  534. package/apps/app-lifeops/src/components/LifeOpsSectionContent.js +0 -30
  535. package/apps/app-lifeops/src/components/LifeOpsSelectionContext.d.ts +0 -21
  536. package/apps/app-lifeops/src/components/LifeOpsSelectionContext.d.ts.map +0 -1
  537. package/apps/app-lifeops/src/components/LifeOpsSelectionContext.js +0 -30
  538. package/apps/app-lifeops/src/components/LifeOpsSettingsSection.d.ts +0 -20
  539. package/apps/app-lifeops/src/components/LifeOpsSettingsSection.d.ts.map +0 -1
  540. package/apps/app-lifeops/src/components/LifeOpsSettingsSection.js +0 -597
  541. package/apps/app-lifeops/src/components/LifeOpsSetupGate.d.ts +0 -13
  542. package/apps/app-lifeops/src/components/LifeOpsSetupGate.d.ts.map +0 -1
  543. package/apps/app-lifeops/src/components/LifeOpsSetupGate.js +0 -134
  544. package/apps/app-lifeops/src/components/LifeOpsSleepSection.d.ts +0 -10
  545. package/apps/app-lifeops/src/components/LifeOpsSleepSection.d.ts.map +0 -1
  546. package/apps/app-lifeops/src/components/LifeOpsSleepSection.js +0 -425
  547. package/apps/app-lifeops/src/components/LifeOpsWorkspaceShell.d.ts +0 -11
  548. package/apps/app-lifeops/src/components/LifeOpsWorkspaceShell.d.ts.map +0 -1
  549. package/apps/app-lifeops/src/components/LifeOpsWorkspaceShell.js +0 -49
  550. package/apps/app-lifeops/src/components/LifeOpsWorkspaceView.d.ts +0 -2
  551. package/apps/app-lifeops/src/components/LifeOpsWorkspaceView.d.ts.map +0 -1
  552. package/apps/app-lifeops/src/components/LifeOpsWorkspaceView.js +0 -1041
  553. package/apps/app-lifeops/src/components/MessagingConnectorCards.d.ts +0 -7
  554. package/apps/app-lifeops/src/components/MessagingConnectorCards.d.ts.map +0 -1
  555. package/apps/app-lifeops/src/components/MessagingConnectorCards.js +0 -643
  556. package/apps/app-lifeops/src/components/MissingSourceCard.d.ts +0 -9
  557. package/apps/app-lifeops/src/components/MissingSourceCard.d.ts.map +0 -1
  558. package/apps/app-lifeops/src/components/MissingSourceCard.js +0 -5
  559. package/apps/app-lifeops/src/components/MobileSignalsSetupCard.d.ts +0 -2
  560. package/apps/app-lifeops/src/components/MobileSignalsSetupCard.d.ts.map +0 -1
  561. package/apps/app-lifeops/src/components/MobileSignalsSetupCard.js +0 -162
  562. package/apps/app-lifeops/src/components/SleepInspectionPanel.d.ts +0 -8
  563. package/apps/app-lifeops/src/components/SleepInspectionPanel.d.ts.map +0 -1
  564. package/apps/app-lifeops/src/components/SleepInspectionPanel.js +0 -59
  565. package/apps/app-lifeops/src/components/WebsiteBlockerSettingsCard.d.ts +0 -3
  566. package/apps/app-lifeops/src/components/WebsiteBlockerSettingsCard.d.ts.map +0 -1
  567. package/apps/app-lifeops/src/components/WebsiteBlockerSettingsCard.js +0 -75
  568. package/apps/app-lifeops/src/components/WhatsAppQrOverlay.d.ts +0 -8
  569. package/apps/app-lifeops/src/components/WhatsAppQrOverlay.d.ts.map +0 -1
  570. package/apps/app-lifeops/src/components/WhatsAppQrOverlay.js +0 -48
  571. package/apps/app-lifeops/src/components/lifeops-labels.d.ts +0 -2
  572. package/apps/app-lifeops/src/components/lifeops-labels.d.ts.map +0 -1
  573. package/apps/app-lifeops/src/components/lifeops-labels.js +0 -5
  574. package/apps/app-lifeops/src/events/index.d.ts +0 -34
  575. package/apps/app-lifeops/src/events/index.d.ts.map +0 -1
  576. package/apps/app-lifeops/src/events/index.js +0 -23
  577. package/apps/app-lifeops/src/followup/actions/listOverdueFollowups.d.ts +0 -3
  578. package/apps/app-lifeops/src/followup/actions/listOverdueFollowups.d.ts.map +0 -1
  579. package/apps/app-lifeops/src/followup/actions/listOverdueFollowups.js +0 -48
  580. package/apps/app-lifeops/src/followup/actions/markFollowupDone.d.ts +0 -3
  581. package/apps/app-lifeops/src/followup/actions/markFollowupDone.d.ts.map +0 -1
  582. package/apps/app-lifeops/src/followup/actions/markFollowupDone.js +0 -173
  583. package/apps/app-lifeops/src/followup/actions/setFollowupThreshold.d.ts +0 -3
  584. package/apps/app-lifeops/src/followup/actions/setFollowupThreshold.d.ts.map +0 -1
  585. package/apps/app-lifeops/src/followup/actions/setFollowupThreshold.js +0 -172
  586. package/apps/app-lifeops/src/followup/followup-tracker.d.ts +0 -82
  587. package/apps/app-lifeops/src/followup/followup-tracker.d.ts.map +0 -1
  588. package/apps/app-lifeops/src/followup/followup-tracker.js +0 -279
  589. package/apps/app-lifeops/src/followup/index.d.ts +0 -5
  590. package/apps/app-lifeops/src/followup/index.d.ts.map +0 -1
  591. package/apps/app-lifeops/src/followup/index.js +0 -4
  592. package/apps/app-lifeops/src/hooks/useCalendarWeek.d.ts +0 -28
  593. package/apps/app-lifeops/src/hooks/useCalendarWeek.d.ts.map +0 -1
  594. package/apps/app-lifeops/src/hooks/useCalendarWeek.js +0 -93
  595. package/apps/app-lifeops/src/hooks/useDiscordConnector.d.ts +0 -14
  596. package/apps/app-lifeops/src/hooks/useDiscordConnector.d.ts.map +0 -1
  597. package/apps/app-lifeops/src/hooks/useDiscordConnector.js +0 -126
  598. package/apps/app-lifeops/src/hooks/useGoogleLifeOpsConnector.d.ts +0 -29
  599. package/apps/app-lifeops/src/hooks/useGoogleLifeOpsConnector.d.ts.map +0 -1
  600. package/apps/app-lifeops/src/hooks/useGoogleLifeOpsConnector.js +0 -481
  601. package/apps/app-lifeops/src/hooks/useIMessageConnector.d.ts +0 -10
  602. package/apps/app-lifeops/src/hooks/useIMessageConnector.d.ts.map +0 -1
  603. package/apps/app-lifeops/src/hooks/useIMessageConnector.js +0 -50
  604. package/apps/app-lifeops/src/hooks/useInbox.d.ts +0 -34
  605. package/apps/app-lifeops/src/hooks/useInbox.d.ts.map +0 -1
  606. package/apps/app-lifeops/src/hooks/useInbox.js +0 -98
  607. package/apps/app-lifeops/src/hooks/useLifeOpsActivitySignals.d.ts +0 -2
  608. package/apps/app-lifeops/src/hooks/useLifeOpsActivitySignals.d.ts.map +0 -1
  609. package/apps/app-lifeops/src/hooks/useLifeOpsActivitySignals.js +0 -382
  610. package/apps/app-lifeops/src/hooks/useLifeOpsAppState.d.ts +0 -21
  611. package/apps/app-lifeops/src/hooks/useLifeOpsAppState.d.ts.map +0 -1
  612. package/apps/app-lifeops/src/hooks/useLifeOpsAppState.js +0 -83
  613. package/apps/app-lifeops/src/hooks/useLifeOpsCapabilitiesStatus.d.ts +0 -8
  614. package/apps/app-lifeops/src/hooks/useLifeOpsCapabilitiesStatus.d.ts.map +0 -1
  615. package/apps/app-lifeops/src/hooks/useLifeOpsCapabilitiesStatus.js +0 -60
  616. package/apps/app-lifeops/src/hooks/useLifeOpsScheduleInspection.d.ts +0 -18
  617. package/apps/app-lifeops/src/hooks/useLifeOpsScheduleInspection.d.ts.map +0 -1
  618. package/apps/app-lifeops/src/hooks/useLifeOpsScheduleInspection.js +0 -66
  619. package/apps/app-lifeops/src/hooks/useLifeOpsScheduleState.d.ts +0 -14
  620. package/apps/app-lifeops/src/hooks/useLifeOpsScheduleState.d.ts.map +0 -1
  621. package/apps/app-lifeops/src/hooks/useLifeOpsScheduleState.js +0 -79
  622. package/apps/app-lifeops/src/hooks/useLifeOpsSection.d.ts +0 -18
  623. package/apps/app-lifeops/src/hooks/useLifeOpsSection.d.ts.map +0 -1
  624. package/apps/app-lifeops/src/hooks/useLifeOpsSection.js +0 -78
  625. package/apps/app-lifeops/src/hooks/useLifeOpsXConnector.d.ts +0 -14
  626. package/apps/app-lifeops/src/hooks/useLifeOpsXConnector.d.ts.map +0 -1
  627. package/apps/app-lifeops/src/hooks/useLifeOpsXConnector.js +0 -160
  628. package/apps/app-lifeops/src/hooks/useSignalConnector.d.ts +0 -16
  629. package/apps/app-lifeops/src/hooks/useSignalConnector.d.ts.map +0 -1
  630. package/apps/app-lifeops/src/hooks/useSignalConnector.js +0 -198
  631. package/apps/app-lifeops/src/hooks/useTelegramConnector.d.ts +0 -21
  632. package/apps/app-lifeops/src/hooks/useTelegramConnector.d.ts.map +0 -1
  633. package/apps/app-lifeops/src/hooks/useTelegramConnector.js +0 -177
  634. package/apps/app-lifeops/src/hooks/useWhatsAppConnector.d.ts +0 -8
  635. package/apps/app-lifeops/src/hooks/useWhatsAppConnector.d.ts.map +0 -1
  636. package/apps/app-lifeops/src/hooks/useWhatsAppConnector.js +0 -58
  637. package/apps/app-lifeops/src/hooks/useWhatsAppPairing.d.ts +0 -12
  638. package/apps/app-lifeops/src/hooks/useWhatsAppPairing.d.ts.map +0 -1
  639. package/apps/app-lifeops/src/hooks/useWhatsAppPairing.js +0 -152
  640. package/apps/app-lifeops/src/inbox/config.d.ts +0 -7
  641. package/apps/app-lifeops/src/inbox/config.d.ts.map +0 -1
  642. package/apps/app-lifeops/src/inbox/config.js +0 -67
  643. package/apps/app-lifeops/src/inbox/reflection.d.ts +0 -40
  644. package/apps/app-lifeops/src/inbox/reflection.d.ts.map +0 -1
  645. package/apps/app-lifeops/src/inbox/reflection.js +0 -115
  646. package/apps/app-lifeops/src/inbox/repository.d.ts +0 -52
  647. package/apps/app-lifeops/src/inbox/repository.d.ts.map +0 -1
  648. package/apps/app-lifeops/src/inbox/repository.js +0 -262
  649. package/apps/app-lifeops/src/inbox/triage-classifier.d.ts +0 -15
  650. package/apps/app-lifeops/src/inbox/triage-classifier.d.ts.map +0 -1
  651. package/apps/app-lifeops/src/inbox/triage-classifier.js +0 -179
  652. package/apps/app-lifeops/src/index.d.ts +0 -20
  653. package/apps/app-lifeops/src/index.d.ts.map +0 -1
  654. package/apps/app-lifeops/src/index.js +0 -18
  655. package/apps/app-lifeops/src/lifeops/approval-queue.d.ts +0 -24
  656. package/apps/app-lifeops/src/lifeops/approval-queue.d.ts.map +0 -1
  657. package/apps/app-lifeops/src/lifeops/approval-queue.js +0 -500
  658. package/apps/app-lifeops/src/lifeops/approval-queue.types.d.ts +0 -166
  659. package/apps/app-lifeops/src/lifeops/approval-queue.types.d.ts.map +0 -1
  660. package/apps/app-lifeops/src/lifeops/approval-queue.types.js +0 -22
  661. package/apps/app-lifeops/src/lifeops/autofill-whitelist.d.ts +0 -15
  662. package/apps/app-lifeops/src/lifeops/autofill-whitelist.d.ts.map +0 -1
  663. package/apps/app-lifeops/src/lifeops/autofill-whitelist.js +0 -116
  664. package/apps/app-lifeops/src/lifeops/background-planner-dispatch.d.ts +0 -60
  665. package/apps/app-lifeops/src/lifeops/background-planner-dispatch.d.ts.map +0 -1
  666. package/apps/app-lifeops/src/lifeops/background-planner-dispatch.js +0 -134
  667. package/apps/app-lifeops/src/lifeops/background-planner.d.ts +0 -141
  668. package/apps/app-lifeops/src/lifeops/background-planner.d.ts.map +0 -1
  669. package/apps/app-lifeops/src/lifeops/background-planner.js +0 -377
  670. package/apps/app-lifeops/src/lifeops/calendly-client.d.ts +0 -61
  671. package/apps/app-lifeops/src/lifeops/calendly-client.d.ts.map +0 -1
  672. package/apps/app-lifeops/src/lifeops/calendly-client.js +0 -234
  673. package/apps/app-lifeops/src/lifeops/checkin/schedule-resolver.d.ts +0 -14
  674. package/apps/app-lifeops/src/lifeops/checkin/schedule-resolver.d.ts.map +0 -1
  675. package/apps/app-lifeops/src/lifeops/checkin/schedule-resolver.js +0 -27
  676. package/apps/app-lifeops/src/lifeops/cross-channel-search.d.ts +0 -88
  677. package/apps/app-lifeops/src/lifeops/cross-channel-search.d.ts.map +0 -1
  678. package/apps/app-lifeops/src/lifeops/cross-channel-search.js +0 -446
  679. package/apps/app-lifeops/src/lifeops/intent-sync.d.ts +0 -59
  680. package/apps/app-lifeops/src/lifeops/intent-sync.d.ts.map +0 -1
  681. package/apps/app-lifeops/src/lifeops/intent-sync.js +0 -305
  682. package/apps/app-lifeops/src/lifeops/notifications-push.d.ts +0 -37
  683. package/apps/app-lifeops/src/lifeops/notifications-push.d.ts.map +0 -1
  684. package/apps/app-lifeops/src/lifeops/notifications-push.js +0 -92
  685. package/apps/app-lifeops/src/lifeops/password-manager-bridge.d.ts +0 -50
  686. package/apps/app-lifeops/src/lifeops/password-manager-bridge.d.ts.map +0 -1
  687. package/apps/app-lifeops/src/lifeops/password-manager-bridge.js +0 -448
  688. package/apps/app-lifeops/src/lifeops/remote-desktop.d.ts +0 -38
  689. package/apps/app-lifeops/src/lifeops/remote-desktop.d.ts.map +0 -1
  690. package/apps/app-lifeops/src/lifeops/remote-desktop.js +0 -372
  691. package/apps/app-lifeops/src/lifeops/runtime.d.ts +0 -11
  692. package/apps/app-lifeops/src/lifeops/runtime.d.ts.map +0 -1
  693. package/apps/app-lifeops/src/lifeops/runtime.js +0 -57
  694. package/apps/app-lifeops/src/lifeops/screen-context.d.ts +0 -52
  695. package/apps/app-lifeops/src/lifeops/screen-context.d.ts.map +0 -1
  696. package/apps/app-lifeops/src/lifeops/screen-context.js +0 -349
  697. package/apps/app-lifeops/src/lifeops-route.d.ts +0 -74
  698. package/apps/app-lifeops/src/lifeops-route.d.ts.map +0 -1
  699. package/apps/app-lifeops/src/lifeops-route.js +0 -204
  700. package/apps/app-lifeops/src/platform/index.d.ts +0 -2
  701. package/apps/app-lifeops/src/platform/index.d.ts.map +0 -1
  702. package/apps/app-lifeops/src/platform/index.js +0 -1
  703. package/apps/app-lifeops/src/platform/lifeops-github.d.ts +0 -15
  704. package/apps/app-lifeops/src/platform/lifeops-github.d.ts.map +0 -1
  705. package/apps/app-lifeops/src/platform/lifeops-github.js +0 -135
  706. package/apps/app-lifeops/src/plugin.d.ts +0 -33
  707. package/apps/app-lifeops/src/plugin.d.ts.map +0 -1
  708. package/apps/app-lifeops/src/plugin.js +0 -316
  709. package/apps/app-lifeops/src/provider.d.ts +0 -4
  710. package/apps/app-lifeops/src/provider.d.ts.map +0 -1
  711. package/apps/app-lifeops/src/provider.js +0 -77
  712. package/apps/app-lifeops/src/providers/activity-profile.d.ts +0 -3
  713. package/apps/app-lifeops/src/providers/activity-profile.d.ts.map +0 -1
  714. package/apps/app-lifeops/src/providers/activity-profile.js +0 -140
  715. package/apps/app-lifeops/src/providers/app-blocker.d.ts +0 -3
  716. package/apps/app-lifeops/src/providers/app-blocker.d.ts.map +0 -1
  717. package/apps/app-lifeops/src/providers/app-blocker.js +0 -86
  718. package/apps/app-lifeops/src/providers/cross-channel-context.d.ts +0 -29
  719. package/apps/app-lifeops/src/providers/cross-channel-context.d.ts.map +0 -1
  720. package/apps/app-lifeops/src/providers/cross-channel-context.js +0 -182
  721. package/apps/app-lifeops/src/providers/inbox-triage.d.ts +0 -3
  722. package/apps/app-lifeops/src/providers/inbox-triage.d.ts.map +0 -1
  723. package/apps/app-lifeops/src/providers/inbox-triage.js +0 -90
  724. package/apps/app-lifeops/src/providers/lifeops.d.ts +0 -3
  725. package/apps/app-lifeops/src/providers/lifeops.d.ts.map +0 -1
  726. package/apps/app-lifeops/src/providers/lifeops.js +0 -197
  727. package/apps/app-lifeops/src/remote/pairing-code.d.ts +0 -39
  728. package/apps/app-lifeops/src/remote/pairing-code.d.ts.map +0 -1
  729. package/apps/app-lifeops/src/remote/pairing-code.js +0 -76
  730. package/apps/app-lifeops/src/remote/remote-session-service.d.ts +0 -107
  731. package/apps/app-lifeops/src/remote/remote-session-service.d.ts.map +0 -1
  732. package/apps/app-lifeops/src/remote/remote-session-service.js +0 -253
  733. package/apps/app-lifeops/src/service.d.ts +0 -32
  734. package/apps/app-lifeops/src/service.d.ts.map +0 -1
  735. package/apps/app-lifeops/src/service.js +0 -67
  736. package/apps/app-lifeops/src/travel-time/calendar-create.d.ts +0 -17
  737. package/apps/app-lifeops/src/travel-time/calendar-create.d.ts.map +0 -1
  738. package/apps/app-lifeops/src/travel-time/calendar-create.js +0 -21
  739. package/apps/app-lifeops/src/travel-time/service.d.ts +0 -60
  740. package/apps/app-lifeops/src/travel-time/service.d.ts.map +0 -1
  741. package/apps/app-lifeops/src/travel-time/service.js +0 -142
  742. package/apps/app-lifeops/src/utils/lifeops-url.d.ts +0 -5
  743. package/apps/app-lifeops/src/utils/lifeops-url.d.ts.map +0 -1
  744. package/apps/app-lifeops/src/utils/lifeops-url.js +0 -35
  745. package/apps/app-lifeops/src/website-blocker/chat-integration/actions/blockUntilTaskComplete.d.ts +0 -3
  746. package/apps/app-lifeops/src/website-blocker/chat-integration/actions/blockUntilTaskComplete.d.ts.map +0 -1
  747. package/apps/app-lifeops/src/website-blocker/chat-integration/actions/blockUntilTaskComplete.js +0 -246
  748. package/apps/app-lifeops/src/website-blocker/chat-integration/actions/listActiveBlocks.d.ts +0 -3
  749. package/apps/app-lifeops/src/website-blocker/chat-integration/actions/listActiveBlocks.d.ts.map +0 -1
  750. package/apps/app-lifeops/src/website-blocker/chat-integration/actions/listActiveBlocks.js +0 -83
  751. package/apps/app-lifeops/src/website-blocker/chat-integration/actions/releaseBlock.d.ts +0 -3
  752. package/apps/app-lifeops/src/website-blocker/chat-integration/actions/releaseBlock.d.ts.map +0 -1
  753. package/apps/app-lifeops/src/website-blocker/chat-integration/actions/releaseBlock.js +0 -98
  754. package/apps/app-lifeops/src/website-blocker/chat-integration/block-rule-reconciler.d.ts +0 -7
  755. package/apps/app-lifeops/src/website-blocker/chat-integration/block-rule-reconciler.d.ts.map +0 -1
  756. package/apps/app-lifeops/src/website-blocker/chat-integration/block-rule-reconciler.js +0 -111
  757. package/apps/app-lifeops/src/website-blocker/chat-integration/block-rule-schema.d.ts +0 -39
  758. package/apps/app-lifeops/src/website-blocker/chat-integration/block-rule-schema.d.ts.map +0 -1
  759. package/apps/app-lifeops/src/website-blocker/chat-integration/block-rule-schema.js +0 -123
  760. package/apps/app-lifeops/src/website-blocker/chat-integration/block-rule-service.d.ts +0 -21
  761. package/apps/app-lifeops/src/website-blocker/chat-integration/block-rule-service.d.ts.map +0 -1
  762. package/apps/app-lifeops/src/website-blocker/chat-integration/block-rule-service.js +0 -258
  763. package/apps/app-lifeops/src/website-blocker/chat-integration/index.d.ts +0 -8
  764. package/apps/app-lifeops/src/website-blocker/chat-integration/index.d.ts.map +0 -1
  765. package/apps/app-lifeops/src/website-blocker/chat-integration/index.js +0 -6
  766. package/packages/app-core/src/api/client-lifeops.d.ts +0 -35
  767. package/packages/app-core/src/api/client-lifeops.d.ts.map +0 -1
  768. package/packages/app-core/src/api/client-lifeops.js +0 -114
  769. package/packages/app-core/src/hooks/useGoogleLifeOpsConnector.d.ts +0 -20
  770. package/packages/app-core/src/hooks/useGoogleLifeOpsConnector.d.ts.map +0 -1
  771. package/packages/app-core/src/hooks/useGoogleLifeOpsConnector.js +0 -69
  772. package/packages/app-core/src/hooks/useLifeOpsAppState.d.ts +0 -21
  773. package/packages/app-core/src/hooks/useLifeOpsAppState.d.ts.map +0 -1
  774. package/packages/app-core/src/hooks/useLifeOpsAppState.js +0 -81
  775. package/packages/app-core/src/services/steward-sidecar.d.ts +0 -6
  776. package/packages/app-core/src/services/steward-sidecar.d.ts.map +0 -1
  777. package/packages/app-core/src/services/steward-sidecar.js +0 -5
@@ -1,3247 +0,0 @@
1
- import { ModelType, parseJSONObjectFromText } from "@elizaos/core";
2
- import { getRecentMessagesData } from "@elizaos/shared";
3
- import { buildNativeAppleReminderMetadata, } from "../lifeops/apple-reminders.js";
4
- import { resolveDefaultTimeZone, resolveDefaultWindowPolicy, } from "../lifeops/defaults.js";
5
- import { LifeOpsService, LifeOpsServiceError } from "../lifeops/service.js";
6
- import { addDaysToLocalDate, buildUtcDateFromLocalParts, getZonedDateParts, } from "../lifeops/time.js";
7
- import { gmailAction } from "./gmail.js";
8
- import { renderGroundedActionReply, } from "@elizaos/agent";
9
- import { extractLifeOperationWithLlm, } from "./life.extractor.js";
10
- import { extractGoalCreatePlanWithLlm, extractGoalUpdatePlanWithLlm, mergeGoalMetadataWithGrounding, } from "./life-goal-extractor.js";
11
- import { extractReminderIntensityWithLlm, extractTaskCreatePlanWithLlm, } from "./life-param-extractor.js";
12
- import { recentConversationTexts } from "./life-recent-context.js";
13
- import { extractUpdateFieldsWithLlm } from "./life-update-extractor.js";
14
- import { calendarReadUnavailableMessage, dayRange, detailArray, detailBoolean, detailNumber, detailObject, detailString, formatCalendarFeed, formatNextEventContext, formatOverviewForQuery, getGoogleCapabilityStatus, hasLifeOpsAccess, INTERNAL_URL, messageText, toActionData, weekRange, } from "./lifeops-google-helpers.js";
15
- import { looksLikeCodingTaskRequest } from "./non-actionable-request.js";
16
- import { normalizeExplicitTimeZoneToken } from "./timezone-normalization.js";
17
- const ACTION_TO_OPERATION = {
18
- create: "create_definition",
19
- create_goal: "create_goal",
20
- update: "update_definition",
21
- update_goal: "update_goal",
22
- delete: "delete_definition",
23
- delete_goal: "delete_goal",
24
- complete: "complete_occurrence",
25
- skip: "skip_occurrence",
26
- snooze: "snooze_occurrence",
27
- review: "review_goal",
28
- phone: "capture_phone",
29
- escalation: "configure_escalation",
30
- reminder_preference: "set_reminder_preference",
31
- calendar: "query_calendar_today",
32
- next_event: "query_calendar_next",
33
- email: "query_email",
34
- overview: "query_overview",
35
- };
36
- const GENERIC_DERIVED_TITLE_RE = /^(?:new\s+)?(?:habit|routine|task|goal|life goal|thing|item|something|anything|stuff|plan|reminder|todo|to do|achieve|achieve a|achieve an)$/i;
37
- /** Maximum age (ms) for a deferred draft before it expires. */
38
- const DRAFT_EXPIRY_MS = 5 * 60 * 1000; // 5 minutes
39
- /** Maximum conversation turns before a deferred draft expires. */
40
- const DRAFT_MAX_TURNS = 3;
41
- function normalizeLifeTimeZoneToken(value) {
42
- return normalizeExplicitTimeZoneToken(value);
43
- }
44
- async function resolveLifeOperationPlan(args) {
45
- const { runtime, message, state, intent, explicitOperation } = args;
46
- if (explicitOperation) {
47
- return {
48
- operation: explicitOperation,
49
- confidence: 1,
50
- missing: [],
51
- shouldAct: true,
52
- };
53
- }
54
- const extracted = await extractLifeOperationWithLlm({
55
- runtime,
56
- message,
57
- state,
58
- intent,
59
- });
60
- if (!extracted.shouldAct || !extracted.operation) {
61
- return {
62
- operation: extracted.operation,
63
- confidence: extracted.confidence,
64
- missing: extracted.missing,
65
- shouldAct: false,
66
- };
67
- }
68
- return {
69
- operation: extracted.operation,
70
- confidence: extracted.confidence,
71
- missing: extracted.missing,
72
- shouldAct: true,
73
- };
74
- }
75
- function shouldForceLifeCreateExecution(args) {
76
- if (args.operation !== "create_definition") {
77
- return false;
78
- }
79
- const blockingFields = args.missing.filter((field) => field !== "title" && field !== "schedule");
80
- if (blockingFields.length > 0) {
81
- return false;
82
- }
83
- if (typeof args.title === "string" && args.title.trim().length > 0) {
84
- return true;
85
- }
86
- if (normalizeCadenceDetail(detailObject(args.details, "cadence"))) {
87
- return true;
88
- }
89
- return false;
90
- }
91
- // ── Helpers ───────────────────────────────────────────
92
- function requestedOwnership(domain) {
93
- if (domain === "agent_ops") {
94
- return { domain: "agent_ops", subjectType: "agent" };
95
- }
96
- return { domain: "user_lifeops", subjectType: "owner" };
97
- }
98
- function normalizeIntentText(value) {
99
- return normalizeLifeInputText(value).toLowerCase();
100
- }
101
- function normalizeLifeInputText(value) {
102
- return value
103
- .replace(/[\u00a0\u1680\u2000-\u200b\u202f\u205f\u3000]/g, " ")
104
- .replace(/\s+/g, " ")
105
- .trim();
106
- }
107
- function normalizeTitle(value) {
108
- return normalizeIntentText(value);
109
- }
110
- function matchByTitle(entries, targetTitle) {
111
- const normalized = normalizeTitle(targetTitle);
112
- return (entries.find((e) => normalizeTitle(e.definition?.title ?? e.goal?.title ?? "") ===
113
- normalized) ??
114
- entries.find((e) => normalizeTitle(e.definition?.title ?? e.goal?.title ?? "").includes(normalized)) ??
115
- null);
116
- }
117
- function coerceDeferredLifeDraft(value) {
118
- if (!value || typeof value !== "object") {
119
- return null;
120
- }
121
- const record = value;
122
- const operation = record.operation;
123
- const intent = typeof record.intent === "string" ? record.intent.trim() : "";
124
- const request = record.request && typeof record.request === "object"
125
- ? record.request
126
- : null;
127
- const createdAt = typeof record.createdAt === "number" && Number.isFinite(record.createdAt)
128
- ? record.createdAt
129
- : undefined;
130
- if (!request || !intent) {
131
- return null;
132
- }
133
- const title = typeof request.title === "string" ? request.title.trim() : "";
134
- if (!title) {
135
- return null;
136
- }
137
- if (operation === "create_definition") {
138
- const kind = typeof request.kind === "string"
139
- ? request.kind
140
- : null;
141
- const cadence = request.cadence;
142
- if (!kind || !cadence) {
143
- return null;
144
- }
145
- return {
146
- createdAt,
147
- intent,
148
- operation,
149
- request: {
150
- cadence,
151
- description: typeof request.description === "string"
152
- ? request.description
153
- : undefined,
154
- goalRef: typeof request.goalRef === "string" ? request.goalRef : undefined,
155
- kind,
156
- priority: typeof request.priority === "number" ? request.priority : undefined,
157
- progressionRule: request.progressionRule,
158
- reminderPlan: request.reminderPlan,
159
- timezone: typeof request.timezone === "string" ? request.timezone : undefined,
160
- title,
161
- metadata: request.metadata && typeof request.metadata === "object"
162
- ? request.metadata
163
- : undefined,
164
- windowPolicy: request.windowPolicy,
165
- websiteAccess: request.websiteAccess,
166
- },
167
- };
168
- }
169
- if (operation === "create_goal") {
170
- return {
171
- createdAt,
172
- intent,
173
- operation,
174
- request: {
175
- cadence: request.cadence,
176
- description: typeof request.description === "string"
177
- ? request.description
178
- : undefined,
179
- metadata: request.metadata && typeof request.metadata === "object"
180
- ? request.metadata
181
- : undefined,
182
- successCriteria: request.successCriteria,
183
- supportStrategy: request.supportStrategy,
184
- title,
185
- },
186
- };
187
- }
188
- return null;
189
- }
190
- function stateActionResults(state) {
191
- if (!state || typeof state !== "object") {
192
- return [];
193
- }
194
- const stateRecord = state;
195
- const data = stateRecord.data && typeof stateRecord.data === "object"
196
- ? stateRecord.data
197
- : undefined;
198
- const providerResults = data?.providers && typeof data.providers === "object"
199
- ? data.providers
200
- : undefined;
201
- const providerActionState = providerResults?.ACTION_STATE &&
202
- typeof providerResults.ACTION_STATE === "object"
203
- ? providerResults.ACTION_STATE
204
- : undefined;
205
- const providerActionStateData = providerActionState?.data && typeof providerActionState.data === "object"
206
- ? providerActionState.data
207
- : undefined;
208
- const providerRecentMessages = providerResults?.RECENT_MESSAGES &&
209
- typeof providerResults.RECENT_MESSAGES === "object"
210
- ? providerResults.RECENT_MESSAGES
211
- : undefined;
212
- const providerRecentMessagesData = providerRecentMessages?.data &&
213
- typeof providerRecentMessages.data === "object"
214
- ? providerRecentMessages.data
215
- : undefined;
216
- const candidates = [
217
- data?.actionResults,
218
- providerActionStateData?.actionResults,
219
- providerActionStateData?.recentActionMemories,
220
- providerRecentMessagesData?.actionResults,
221
- ].filter(Array.isArray);
222
- if (candidates.length === 0) {
223
- return [];
224
- }
225
- return candidates.flatMap((entries) => entries.flatMap((entry) => {
226
- if (!entry || typeof entry !== "object") {
227
- return [];
228
- }
229
- if ("content" in entry) {
230
- const content = entry.content &&
231
- typeof entry.content === "object"
232
- ? entry
233
- .content
234
- : null;
235
- if (!content) {
236
- return [];
237
- }
238
- const contentData = content.data && typeof content.data === "object"
239
- ? { ...content.data }
240
- : {};
241
- if (typeof content.actionName === "string" &&
242
- typeof contentData.actionName !== "string") {
243
- contentData.actionName = content.actionName;
244
- }
245
- return [
246
- {
247
- success: content.actionStatus !== "failed",
248
- text: typeof content.text === "string" ? content.text : undefined,
249
- data: contentData,
250
- error: typeof content.error === "string" ? content.error : undefined,
251
- },
252
- ];
253
- }
254
- return [entry];
255
- }));
256
- }
257
- function stateMessageDrafts(state) {
258
- if (!state || typeof state !== "object") {
259
- return [];
260
- }
261
- const drafts = [];
262
- for (const item of getRecentMessagesData(state)) {
263
- const content = item.content;
264
- if (!content || typeof content !== "object") {
265
- continue;
266
- }
267
- const contentRecord = content;
268
- const candidate = coerceDeferredLifeDraft(contentRecord.lifeDraft) ??
269
- coerceDeferredLifeDraft(contentRecord.data && typeof contentRecord.data === "object"
270
- ? contentRecord.data.lifeDraft
271
- : undefined);
272
- if (candidate) {
273
- drafts.push(candidate);
274
- }
275
- }
276
- return drafts;
277
- }
278
- function stateRecentMessageEntries(state) {
279
- if (!state || typeof state !== "object") {
280
- return [];
281
- }
282
- return getRecentMessagesData(state);
283
- }
284
- function isDeferredLifeDraftMessageEntry(item) {
285
- const content = item.content && typeof item.content === "object"
286
- ? item.content
287
- : null;
288
- if (!content) {
289
- return false;
290
- }
291
- return Boolean(coerceDeferredLifeDraft(content.lifeDraft) ??
292
- coerceDeferredLifeDraft(content.data && typeof content.data === "object"
293
- ? content.data.lifeDraft
294
- : undefined));
295
- }
296
- function countTurnsSinceLatestDeferredLifeDraft(state) {
297
- const entries = stateRecentMessageEntries(state);
298
- if (entries.length === 0) {
299
- return undefined;
300
- }
301
- let latestDraftIndex = -1;
302
- for (let index = entries.length - 1; index >= 0; index--) {
303
- const entry = entries[index];
304
- if (entry && isDeferredLifeDraftMessageEntry(entry)) {
305
- latestDraftIndex = index;
306
- break;
307
- }
308
- }
309
- if (latestDraftIndex < 0) {
310
- return undefined;
311
- }
312
- let turns = 0;
313
- for (const entry of entries.slice(latestDraftIndex + 1)) {
314
- const content = entry.content && typeof entry.content === "object"
315
- ? entry.content
316
- : null;
317
- if (!content || isDeferredLifeDraftMessageEntry(entry)) {
318
- continue;
319
- }
320
- if (typeof content.text === "string" && content.text.trim().length > 0) {
321
- turns++;
322
- }
323
- }
324
- return turns;
325
- }
326
- function latestDeferredLifeDraft(state) {
327
- for (const result of [...stateActionResults(state)].reverse()) {
328
- const resultData = result.data && typeof result.data === "object"
329
- ? result.data
330
- : null;
331
- const completedCreate = result.success &&
332
- resultData &&
333
- !coerceDeferredLifeDraft(resultData.lifeDraft) &&
334
- ((resultData.definition && typeof resultData.definition === "object") ||
335
- (resultData.goal && typeof resultData.goal === "object"));
336
- if (completedCreate) {
337
- return null;
338
- }
339
- const candidate = coerceDeferredLifeDraft(result.data?.lifeDraft);
340
- if (candidate) {
341
- return candidate;
342
- }
343
- }
344
- const messageDrafts = stateMessageDrafts(state);
345
- return messageDrafts.at(-1) ?? null;
346
- }
347
- function deferredLifeDraftExpiryReason(args) {
348
- if (!args.draft) {
349
- return null;
350
- }
351
- if (args.draft.createdAt) {
352
- const ageMs = Date.now() - args.draft.createdAt;
353
- if (ageMs >= DRAFT_EXPIRY_MS) {
354
- return "age";
355
- }
356
- }
357
- if (typeof args.turnsSinceDraft === "number" &&
358
- args.turnsSinceDraft >= DRAFT_MAX_TURNS) {
359
- return "turns";
360
- }
361
- return null;
362
- }
363
- async function extractDeferredLifeDraftFollowupWithLlm(args) {
364
- if (typeof args.runtime.useModel !== "function") {
365
- return null;
366
- }
367
- const recentConversation = await recentConversationTexts({
368
- runtime: args.runtime,
369
- message: args.message,
370
- state: args.state,
371
- limit: 12,
372
- });
373
- const prompt = [
374
- "Decide how the assistant should interpret the user's follow-up to a previewed LifeOps draft that has not been saved yet.",
375
- "Use the current message, the draft summary, and recent conversation.",
376
- "The user may speak in any language.",
377
- "",
378
- "Return ONLY valid JSON with exactly this shape:",
379
- '{"mode":"confirm"|"edit"|"cancel"|"none"}',
380
- "",
381
- "Choose confirm when the user clearly approves saving the current draft now.",
382
- "Choose edit when the user wants to change the draft or continue specifying it before saving.",
383
- "Choose cancel when the user says not to save it, never mind, not yet, hold off, or equivalent.",
384
- "Choose none when the follow-up is unrelated or too ambiguous to attach to the draft.",
385
- "",
386
- "Previewed draft:",
387
- stringifyDeferredLifeDraftForPrompt(args.draft),
388
- "",
389
- `Current user message: ${JSON.stringify(args.currentText)}`,
390
- `Recent conversation: ${JSON.stringify(recentConversation.join("\n"))}`,
391
- ].join("\n");
392
- try {
393
- const result = await args.runtime.useModel(ModelType.TEXT_LARGE, {
394
- prompt,
395
- });
396
- const raw = typeof result === "string" ? result : "";
397
- const parsed = parseJSONObjectFromText(raw);
398
- const mode = parsed && typeof parsed.mode === "string"
399
- ? parsed.mode.trim().toLowerCase()
400
- : "";
401
- switch (mode) {
402
- case "confirm":
403
- case "edit":
404
- case "cancel":
405
- return mode;
406
- default:
407
- return null;
408
- }
409
- }
410
- catch {
411
- return null;
412
- }
413
- }
414
- function stringifyDeferredLifeDraftForPrompt(draft) {
415
- if (draft.operation === "create_definition") {
416
- return JSON.stringify({
417
- operation: draft.operation,
418
- title: draft.request.title,
419
- kind: draft.request.kind,
420
- cadence: draft.request.cadence,
421
- timezone: draft.request.timezone ?? null,
422
- description: draft.request.description ?? null,
423
- });
424
- }
425
- return JSON.stringify({
426
- operation: draft.operation,
427
- title: draft.request.title,
428
- cadence: draft.request.cadence ?? null,
429
- description: draft.request.description ?? null,
430
- });
431
- }
432
- function resolveDeferredLifeDraftReuseMode(args) {
433
- if (!args.draft) {
434
- return null;
435
- }
436
- if (deferredLifeDraftExpiryReason(args)) {
437
- return null;
438
- }
439
- if (detailBoolean(args.details, "confirmed") === true) {
440
- return "confirm";
441
- }
442
- if (args.explicitAction &&
443
- ACTION_TO_OPERATION[args.explicitAction] !== args.draft.operation) {
444
- return null;
445
- }
446
- if (args.llmMode === "confirm" || args.llmMode === "edit") {
447
- return args.llmMode;
448
- }
449
- return null;
450
- }
451
- async function resolveGoal(service, target, domain) {
452
- if (!target)
453
- return null;
454
- const goals = (await service.listGoals()).filter((e) => domain ? e.goal.domain === domain : true);
455
- return goals.find((e) => e.goal.id === target) ?? matchByTitle(goals, target);
456
- }
457
- async function resolveDefinition(service, target, domain) {
458
- if (!target)
459
- return null;
460
- const defs = (await service.listDefinitions()).filter((e) => domain ? e.definition.domain === domain : true);
461
- return (defs.find((e) => e.definition.id === target) ?? matchByTitle(defs, target));
462
- }
463
- function tokenizeTitle(value) {
464
- return normalizeTitle(value)
465
- .split(" ")
466
- .filter((token) => token.length >= 3);
467
- }
468
- async function resolveDefinitionFromIntent(service, target, intent, domain) {
469
- const direct = await resolveDefinition(service, target, domain);
470
- if (direct) {
471
- return direct;
472
- }
473
- const defs = (await service.listDefinitions()).filter((entry) => domain ? entry.definition.domain === domain : true);
474
- const intentTokens = new Set(tokenizeTitle(intent));
475
- let best = null;
476
- let bestScore = 0;
477
- let tied = false;
478
- for (const entry of defs) {
479
- const title = normalizeTitle(entry.definition.title);
480
- if (title.length > 0 && normalizeTitle(intent).includes(title)) {
481
- return entry;
482
- }
483
- const overlap = tokenizeTitle(entry.definition.title).filter((token) => intentTokens.has(token)).length;
484
- if (overlap === 0) {
485
- continue;
486
- }
487
- if (overlap > bestScore) {
488
- best = entry;
489
- bestScore = overlap;
490
- tied = false;
491
- continue;
492
- }
493
- if (overlap === bestScore) {
494
- tied = true;
495
- }
496
- }
497
- return bestScore > 0 && !tied ? best : null;
498
- }
499
- function formatOccurrenceDisambiguationLabel(occurrence) {
500
- const hints = [];
501
- if (typeof occurrence.windowName === "string" &&
502
- occurrence.windowName.trim()) {
503
- hints.push(occurrence.windowName.trim());
504
- }
505
- if (occurrence.dueAt) {
506
- const dueAt = new Date(occurrence.dueAt);
507
- if (!Number.isNaN(dueAt.getTime())) {
508
- hints.push(dueAt.toLocaleString(undefined, {
509
- month: "short",
510
- day: "numeric",
511
- hour: "numeric",
512
- minute: "2-digit",
513
- }));
514
- }
515
- }
516
- return hints.length > 0
517
- ? `${occurrence.title} (${hints.join(", ")})`
518
- : occurrence.title;
519
- }
520
- function narrowOccurrenceCandidates(matches) {
521
- const actionableMatches = matches.filter((occurrence) => occurrence.state === "visible" || occurrence.state === "snoozed");
522
- return actionableMatches.length > 0 ? actionableMatches : matches;
523
- }
524
- async function resolveOccurrence(service, target, domain) {
525
- if (!target)
526
- return { match: null, ambiguousCandidates: [] };
527
- const overview = await service.getOverview();
528
- const all = [
529
- ...overview.owner.occurrences,
530
- ...overview.agentOps.occurrences,
531
- ].filter((o) => (domain ? o.domain === domain : true));
532
- const normalized = normalizeTitle(target);
533
- // Exact ID match
534
- const byId = all.find((o) => o.id === target);
535
- if (byId)
536
- return { match: byId, ambiguousCandidates: [] };
537
- // Exact normalized-title match
538
- const exactMatches = all.filter((o) => normalizeTitle(o.title) === normalized);
539
- if (exactMatches.length === 1) {
540
- return { match: exactMatches.at(0) ?? null, ambiguousCandidates: [] };
541
- }
542
- if (exactMatches.length > 1) {
543
- const narrowedMatches = narrowOccurrenceCandidates(exactMatches);
544
- if (narrowedMatches.length === 1) {
545
- return { match: narrowedMatches.at(0) ?? null, ambiguousCandidates: [] };
546
- }
547
- return {
548
- match: null,
549
- ambiguousCandidates: narrowedMatches.map(formatOccurrenceDisambiguationLabel),
550
- };
551
- }
552
- // Substring matches — disambiguate when multiple
553
- const substringMatches = all.filter((o) => normalizeTitle(o.title).includes(normalized));
554
- if (substringMatches.length === 1) {
555
- return { match: substringMatches.at(0) ?? null, ambiguousCandidates: [] };
556
- }
557
- if (substringMatches.length > 1) {
558
- const narrowedSubstringMatches = narrowOccurrenceCandidates(substringMatches);
559
- if (narrowedSubstringMatches.length === 1) {
560
- return {
561
- match: narrowedSubstringMatches.at(0) ?? null,
562
- ambiguousCandidates: [],
563
- };
564
- }
565
- // Prefer startsWith over generic includes
566
- const startsWithMatches = narrowedSubstringMatches.filter((o) => normalizeTitle(o.title).startsWith(normalized));
567
- if (startsWithMatches.length === 1) {
568
- return { match: startsWithMatches.at(0) ?? null, ambiguousCandidates: [] };
569
- }
570
- if (startsWithMatches.length > 1) {
571
- return {
572
- match: null,
573
- ambiguousCandidates: startsWithMatches.map(formatOccurrenceDisambiguationLabel),
574
- };
575
- }
576
- // Still ambiguous — return candidates for the caller to list
577
- return {
578
- match: null,
579
- ambiguousCandidates: narrowedSubstringMatches.map(formatOccurrenceDisambiguationLabel),
580
- };
581
- }
582
- const targetTokens = normalized.split(/\s+/).filter(Boolean);
583
- if (targetTokens.length > 1) {
584
- const tokenSetMatches = all.filter((occurrence) => {
585
- const occurrenceTokens = new Set(normalizeTitle(occurrence.title).split(/\s+/).filter(Boolean));
586
- return targetTokens.every((token) => occurrenceTokens.has(token));
587
- });
588
- if (tokenSetMatches.length === 1) {
589
- return { match: tokenSetMatches.at(0) ?? null, ambiguousCandidates: [] };
590
- }
591
- if (tokenSetMatches.length > 1) {
592
- const narrowedTokenSetMatches = narrowOccurrenceCandidates(tokenSetMatches);
593
- if (narrowedTokenSetMatches.length === 1) {
594
- return {
595
- match: narrowedTokenSetMatches.at(0) ?? null,
596
- ambiguousCandidates: [],
597
- };
598
- }
599
- return {
600
- match: null,
601
- ambiguousCandidates: narrowedTokenSetMatches.map(formatOccurrenceDisambiguationLabel),
602
- };
603
- }
604
- }
605
- return { match: null, ambiguousCandidates: [] };
606
- }
607
- function deriveOccurrenceTargetFromIntent(intent, operation) {
608
- const normalized = normalizeLifeInputText(intent);
609
- if (!normalized) {
610
- return null;
611
- }
612
- let candidate = normalized;
613
- if (operation === "snooze_occurrence") {
614
- candidate = candidate
615
- .replace(/^(?:please\s+)?(?:snooze|postpone|push\b.*\bback|remind me later about)\s+/i, "")
616
- .replace(/\bfor\s+\d+\s*(?:minutes?|hours?)\b.*$/i, "")
617
- .replace(/\b(?:until|til)\b.+$/i, "")
618
- .trim();
619
- }
620
- else if (operation === "skip_occurrence") {
621
- candidate = candidate
622
- .replace(/^(?:please\s+)?(?:skip|pass on)\s+/i, "")
623
- .replace(/\b(?:today|tonight|for now)\b.*$/i, "")
624
- .trim();
625
- }
626
- else if (operation === "complete_occurrence") {
627
- candidate = candidate
628
- .replace(/^(?:please\s+)?(?:mark\s+|i(?:'ve| have)?\s+|just\s+)?(?:done|completed|finished|did)\s+/i, "")
629
- .replace(/\b(?:done|complete|completed|finished)\b.*$/i, "")
630
- .trim();
631
- }
632
- return candidate.length > 0 ? candidate : null;
633
- }
634
- async function resolveOccurrenceWithIntentFallback(args) {
635
- const direct = await resolveOccurrence(args.service, args.target, args.domain);
636
- if (direct.match || direct.ambiguousCandidates.length > 0) {
637
- return direct;
638
- }
639
- const fallbackTarget = deriveOccurrenceTargetFromIntent(args.intent, args.operation);
640
- if (!fallbackTarget ||
641
- (args.target &&
642
- normalizeTitle(fallbackTarget) === normalizeTitle(args.target))) {
643
- return direct;
644
- }
645
- return resolveOccurrence(args.service, fallbackTarget, args.domain);
646
- }
647
- function summarizeCadence(cadence) {
648
- const cadenceWindows = Array.isArray(cadence.windows)
649
- ? (cadence.windows ?? []).filter((windowName) => typeof windowName === "string" && windowName.trim().length > 0)
650
- : [];
651
- switch (cadence.kind) {
652
- case "once": {
653
- const dueAt = new Date(cadence.dueAt);
654
- if (Number.isNaN(dueAt.getTime())) {
655
- return "once";
656
- }
657
- return `once on ${dueAt.toLocaleString(undefined, {
658
- month: "short",
659
- day: "numeric",
660
- hour: "numeric",
661
- minute: "2-digit",
662
- timeZone: resolveDefaultTimeZone(),
663
- })}`;
664
- }
665
- case "daily":
666
- return cadenceWindows.length > 0
667
- ? `every day in ${cadenceWindows.join(", ")}`
668
- : "every day";
669
- case "times_per_day":
670
- return cadence.slots
671
- .map((slot) => slot.label?.trim() || `${slot.minuteOfDay}`)
672
- .filter(Boolean)
673
- .join(" and ");
674
- case "interval":
675
- return cadenceWindows.length > 0
676
- ? `every ${cadence.everyMinutes} minutes in ${cadenceWindows.join(", ")}`
677
- : `every ${cadence.everyMinutes} minutes`;
678
- case "weekly":
679
- return `weekly on ${cadence.weekdays
680
- .map((weekday) => [
681
- "Sunday",
682
- "Monday",
683
- "Tuesday",
684
- "Wednesday",
685
- "Thursday",
686
- "Friday",
687
- "Saturday",
688
- ][weekday] ?? String(weekday))
689
- .join(", ")}`;
690
- }
691
- }
692
- function buildRuleBasedLifeReply(args) {
693
- const context = args.context ?? {};
694
- const updated = context.updated && typeof context.updated === "object"
695
- ? context.updated
696
- : null;
697
- const created = context.created && typeof context.created === "object"
698
- ? context.created
699
- : null;
700
- const title = (typeof updated?.title === "string" ? updated.title : null) ??
701
- (typeof created?.title === "string" ? created.title : null) ??
702
- (typeof context.title === "string" ? context.title : null) ??
703
- null;
704
- // Time-phrase nuance ("mornings now", "7pm now", etc.) is rendered by the
705
- // LLM in renderGroundedActionReply via the additionalRules contract. The
706
- // rule-based fallback intentionally only carries the title — never tries
707
- // to parse English-only time phrases out of the intent.
708
- switch (args.scenario) {
709
- case "updated_definition":
710
- if (title) {
711
- return `${title} is updated.`;
712
- }
713
- break;
714
- case "deleted_definition":
715
- if (title) {
716
- return `${title} is off your list.`;
717
- }
718
- break;
719
- case "deleted_goal":
720
- if (title) {
721
- return `${title} is off your goals list.`;
722
- }
723
- break;
724
- case "completed_occurrence":
725
- if (title) {
726
- return `Marked ${title} done.`;
727
- }
728
- break;
729
- case "skipped_occurrence":
730
- if (title) {
731
- return `Okay, skipping ${title} for now.`;
732
- }
733
- break;
734
- case "snoozed_occurrence":
735
- if (title) {
736
- return `Okay, I'll bring ${title} back a bit later.`;
737
- }
738
- break;
739
- default:
740
- break;
741
- }
742
- return args.fallback;
743
- }
744
- async function renderLifeActionReply(args) {
745
- const { runtime, message, state, intent, scenario, fallback, context } = args;
746
- const naturalFallback = buildRuleBasedLifeReply({
747
- scenario,
748
- intent,
749
- fallback,
750
- context,
751
- });
752
- return renderGroundedActionReply({
753
- runtime,
754
- message,
755
- state,
756
- intent,
757
- domain: "lifeops",
758
- scenario,
759
- fallback: naturalFallback,
760
- context,
761
- preferCharacterVoice: true,
762
- additionalRules: [
763
- "Mirror the user's phrasing for time and date when possible.",
764
- "Prefer phrases like tomorrow morning, every night, 7 am, or the user's own wording over robotic schedule language.",
765
- "Never surface raw ISO timestamps unless the user used raw ISO timestamps.",
766
- "If this is a preview, make clear it is not saved yet and the user can confirm or change it naturally.",
767
- "If this is reply-only, do not pretend you saved or changed anything.",
768
- ],
769
- });
770
- }
771
- function buildLifeClarificationFallback(args) {
772
- const missing = new Set(args.missing);
773
- if (args.operation === "create_goal") {
774
- return "What do you want the goal to be?";
775
- }
776
- if (missing.has("title") && missing.has("schedule")) {
777
- return "What do you want the todo to be, and when should it happen?";
778
- }
779
- if (missing.has("title")) {
780
- return "What do you want it to be?";
781
- }
782
- if (missing.has("schedule")) {
783
- return "When should it happen?";
784
- }
785
- return "Tell me a bit more about what you want to set up.";
786
- }
787
- function buildLifeServiceErrorFallback(error, intent) {
788
- const normalized = error.message.toLowerCase();
789
- if (normalized.includes("utc 'z' suffix") ||
790
- normalized.includes("local datetime without 'z'") ||
791
- normalized.includes("time didn't parse") ||
792
- normalized.includes("invalid dueat") ||
793
- normalized.includes("cadence.dueat")) {
794
- return `I couldn't pin down the reminder time from "${intent}". Tell me the time again in plain language, like "Friday at 8 pm Pacific."`;
795
- }
796
- if (normalized.includes("when windowpreset is not provided") ||
797
- normalized.includes("startat is required")) {
798
- return "I still need the time for that reminder. Tell me when it should happen.";
799
- }
800
- if (error.status === 429 || normalized.includes("rate limit")) {
801
- return "LifeOps is rate-limited right now. Try again in a bit.";
802
- }
803
- return "I couldn't finish that LifeOps change yet. Tell me the task and timing again, and I'll try it a different way.";
804
- }
805
- // ── Calendar/email formatters ─────────────────────────
806
- const DEFAULT_WINDOW_SLOT_TIMES = {
807
- morning: {
808
- minuteOfDay: 8 * 60,
809
- durationMinutes: 45,
810
- label: "Morning",
811
- },
812
- afternoon: {
813
- minuteOfDay: 13 * 60,
814
- durationMinutes: 45,
815
- label: "Afternoon",
816
- },
817
- evening: {
818
- minuteOfDay: 18 * 60,
819
- durationMinutes: 45,
820
- label: "Evening",
821
- },
822
- night: {
823
- minuteOfDay: 21 * 60,
824
- durationMinutes: 45,
825
- label: "Night",
826
- },
827
- };
828
- function buildSlotsFromWindows(windows) {
829
- return windows.map((window, index) => {
830
- const preset = DEFAULT_WINDOW_SLOT_TIMES[window];
831
- return {
832
- key: windows.indexOf(window) === index ? window : `${window}-${index + 1}`,
833
- label: preset.label,
834
- minuteOfDay: preset.minuteOfDay,
835
- durationMinutes: preset.durationMinutes,
836
- };
837
- });
838
- }
839
- function buildDistributedDailySlots(count) {
840
- const normalizedCount = Math.max(1, Math.min(6, count));
841
- let minutes;
842
- switch (normalizedCount) {
843
- case 1:
844
- minutes = [9 * 60];
845
- break;
846
- case 2:
847
- minutes = [8 * 60, 21 * 60];
848
- break;
849
- case 3:
850
- minutes = [8 * 60, 13 * 60, 20 * 60];
851
- break;
852
- case 4:
853
- minutes = [8 * 60, 12 * 60, 16 * 60, 20 * 60];
854
- break;
855
- case 5:
856
- minutes = [8 * 60, 11 * 60, 14 * 60, 17 * 60, 20 * 60];
857
- break;
858
- default:
859
- minutes = [8 * 60, 10 * 60, 12 * 60, 14 * 60, 17 * 60, 20 * 60];
860
- break;
861
- }
862
- return minutes.map((minuteOfDay, index) => ({
863
- key: `slot-${index + 1}`,
864
- label: `Time ${index + 1}`,
865
- minuteOfDay,
866
- durationMinutes: 45,
867
- }));
868
- }
869
- function inferWindowFromMinuteOfDay(minuteOfDay) {
870
- if (minuteOfDay < 12 * 60) {
871
- return "morning";
872
- }
873
- if (minuteOfDay < 17 * 60) {
874
- return "afternoon";
875
- }
876
- if (minuteOfDay < 21 * 60) {
877
- return "evening";
878
- }
879
- return "night";
880
- }
881
- function buildSingleDailySlot(minuteOfDay, durationMinutes = 45) {
882
- return {
883
- key: `time-${minuteOfDay}`,
884
- label: formatMinuteOfDayLabel(minuteOfDay),
885
- minuteOfDay,
886
- durationMinutes,
887
- };
888
- }
889
- function buildCustomTimeWindowPolicy(minuteOfDay, timeZone) {
890
- const basePolicy = resolveDefaultWindowPolicy(timeZone);
891
- return {
892
- timezone: basePolicy.timezone,
893
- windows: [
894
- ...basePolicy.windows,
895
- {
896
- name: "custom",
897
- label: formatMinuteOfDayLabel(minuteOfDay),
898
- startMinute: minuteOfDay,
899
- endMinute: Math.min(minuteOfDay + 1, 24 * 60),
900
- },
901
- ],
902
- };
903
- }
904
- function formatMinuteOfDayLabel(minuteOfDay) {
905
- const hour24 = Math.floor(minuteOfDay / 60);
906
- const minute = minuteOfDay % 60;
907
- const meridiem = hour24 >= 12 ? "pm" : "am";
908
- const hour12 = hour24 % 12 === 0 ? 12 : hour24 % 12;
909
- return minute === 0
910
- ? `${hour12}${meridiem}`
911
- : `${hour12}:${String(minute).padStart(2, "0")}${meridiem}`;
912
- }
913
- function parseClockToken(token) {
914
- const normalized = token.trim().toLowerCase();
915
- if (normalized === "noon") {
916
- return 12 * 60;
917
- }
918
- if (normalized === "midnight") {
919
- return 0;
920
- }
921
- const match = normalized.match(/^(\d{1,2})(?::(\d{2}))?\s*(am|pm)$/);
922
- if (!match) {
923
- return null;
924
- }
925
- const hour = Number(match[1]);
926
- const minute = Number(match[2] ?? "0");
927
- if (!Number.isFinite(hour) || !Number.isFinite(minute) || minute >= 60) {
928
- return null;
929
- }
930
- if (hour < 1 || hour > 12) {
931
- return null;
932
- }
933
- const meridiem = match[3];
934
- const normalizedHour = meridiem === "am" ? hour % 12 : hour % 12 === 0 ? 12 : (hour % 12) + 12;
935
- return normalizedHour * 60 + minute;
936
- }
937
- function parseTimeOfDayToken(token) {
938
- const normalized = normalizeLifeInputText(token).toLowerCase();
939
- const hhmmMatch = normalized.match(/^(\d{1,2}):(\d{2})$/);
940
- if (hhmmMatch) {
941
- const hour = Number(hhmmMatch[1]);
942
- const minute = Number(hhmmMatch[2]);
943
- if (Number.isFinite(hour) &&
944
- Number.isFinite(minute) &&
945
- hour >= 0 &&
946
- hour <= 23 &&
947
- minute >= 0 &&
948
- minute < 60) {
949
- return hour * 60 + minute;
950
- }
951
- }
952
- return parseClockToken(normalized);
953
- }
954
- function buildOneOffDueAtFromMinuteOfDay(args) {
955
- const now = args.now ?? new Date();
956
- const timeZone = args.timeZone ?? resolveDefaultTimeZone();
957
- const nowParts = getZonedDateParts(now, timeZone);
958
- let localDate = {
959
- year: nowParts.year,
960
- month: nowParts.month,
961
- day: nowParts.day,
962
- };
963
- const buildCandidate = () => buildUtcDateFromLocalParts(timeZone, {
964
- ...localDate,
965
- hour: Math.floor(args.minuteOfDay / 60),
966
- minute: args.minuteOfDay % 60,
967
- second: 0,
968
- });
969
- let candidate = buildCandidate();
970
- if (candidate.getTime() <= now.getTime()) {
971
- localDate = addDaysToLocalDate(localDate, 1);
972
- candidate = buildCandidate();
973
- }
974
- return candidate.toISOString();
975
- }
976
- function mergeMetadataRecords(...records) {
977
- const merged = Object.assign({}, ...records.filter((record) => record != null && Object.keys(record).length > 0));
978
- return Object.keys(merged).length > 0 ? merged : undefined;
979
- }
980
- function extractExplicitDailySlots(intent) {
981
- const tokens = [
982
- ...intent.matchAll(/\b(\d{1,2}(?::\d{2})?\s*(?:am|pm)|noon|midnight)\b/gi),
983
- ]
984
- .map((match) => match[1])
985
- .filter((token) => typeof token === "string" && token.length > 0);
986
- const seen = new Set();
987
- const slots = [];
988
- for (const [index, token] of tokens.entries()) {
989
- const minuteOfDay = parseClockToken(token);
990
- if (minuteOfDay === null || seen.has(minuteOfDay)) {
991
- continue;
992
- }
993
- seen.add(minuteOfDay);
994
- slots.push({
995
- key: `clock-${index + 1}`,
996
- label: token.trim(),
997
- minuteOfDay,
998
- durationMinutes: 45,
999
- });
1000
- }
1001
- return slots.sort((left, right) => left.minuteOfDay - right.minuteOfDay);
1002
- }
1003
- function normalizeLifeWindows(value) {
1004
- const values = Array.isArray(value) ? value : value == null ? [] : [value];
1005
- const normalized = values.flatMap((entry) => {
1006
- if (typeof entry !== "string") {
1007
- return [];
1008
- }
1009
- const lower = normalizeLifeInputText(entry).toLowerCase();
1010
- if (lower === "morning")
1011
- return ["morning"];
1012
- if (lower === "afternoon")
1013
- return ["afternoon"];
1014
- if (lower === "evening")
1015
- return ["evening"];
1016
- if (lower === "night")
1017
- return ["night"];
1018
- return [];
1019
- });
1020
- return [...new Set(normalized)];
1021
- }
1022
- function normalizeCadenceDetail(value) {
1023
- if (!value || typeof value !== "object" || Array.isArray(value)) {
1024
- return undefined;
1025
- }
1026
- const record = value;
1027
- const cadenceKind = typeof record.kind === "string"
1028
- ? normalizeLifeInputText(record.kind).toLowerCase()
1029
- : typeof record.type === "string"
1030
- ? normalizeLifeInputText(record.type).toLowerCase()
1031
- : "";
1032
- if (!cadenceKind) {
1033
- return undefined;
1034
- }
1035
- if (cadenceKind === "once" && typeof record.dueAt === "string") {
1036
- return {
1037
- kind: "once",
1038
- dueAt: record.dueAt,
1039
- };
1040
- }
1041
- if (cadenceKind === "interval") {
1042
- const everyMinutes = typeof record.everyMinutes === "number"
1043
- ? record.everyMinutes
1044
- : typeof record.everyMinutes === "string"
1045
- ? Number(record.everyMinutes)
1046
- : typeof record.minutes === "number"
1047
- ? record.minutes
1048
- : typeof record.minutes === "string"
1049
- ? Number(record.minutes)
1050
- : NaN;
1051
- if (Number.isFinite(everyMinutes) && everyMinutes > 0) {
1052
- return {
1053
- kind: "interval",
1054
- everyMinutes,
1055
- windows: normalizeLifeWindows(record.windows),
1056
- };
1057
- }
1058
- return undefined;
1059
- }
1060
- if (cadenceKind === "weekly") {
1061
- const weekdays = Array.isArray(record.weekdays)
1062
- ? record.weekdays
1063
- .map((entry) => typeof entry === "number"
1064
- ? entry
1065
- : typeof entry === "string"
1066
- ? Number(entry)
1067
- : NaN)
1068
- .filter((entry) => Number.isFinite(entry))
1069
- : [];
1070
- if (weekdays.length > 0) {
1071
- return {
1072
- kind: "weekly",
1073
- weekdays,
1074
- windows: normalizeLifeWindows(record.windows),
1075
- };
1076
- }
1077
- return undefined;
1078
- }
1079
- const explicitTimes = Array.isArray(record.times)
1080
- ? record.times
1081
- .map((entry) => typeof entry === "string" ? parseTimeOfDayToken(entry) : null)
1082
- .filter((entry) => entry !== null)
1083
- : [];
1084
- if (explicitTimes.length > 0) {
1085
- return {
1086
- kind: "times_per_day",
1087
- slots: explicitTimes.map((minuteOfDay, index) => ({
1088
- key: `time-${index + 1}`,
1089
- label: formatMinuteOfDayLabel(minuteOfDay),
1090
- minuteOfDay,
1091
- durationMinutes: 45,
1092
- })),
1093
- visibilityLeadMinutes: 90,
1094
- visibilityLagMinutes: 180,
1095
- };
1096
- }
1097
- if (cadenceKind === "times_per_day") {
1098
- if (Array.isArray(record.slots)) {
1099
- const slots = record.slots
1100
- .map((entry, index) => {
1101
- if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
1102
- return null;
1103
- }
1104
- const slot = entry;
1105
- const minuteOfDay = typeof slot.minuteOfDay === "number"
1106
- ? slot.minuteOfDay
1107
- : typeof slot.minuteOfDay === "string"
1108
- ? Number(slot.minuteOfDay)
1109
- : null;
1110
- if (minuteOfDay === null || !Number.isFinite(minuteOfDay)) {
1111
- return null;
1112
- }
1113
- return {
1114
- key: typeof slot.key === "string" && slot.key.trim().length > 0
1115
- ? slot.key
1116
- : `slot-${index + 1}`,
1117
- label: typeof slot.label === "string" && slot.label.trim().length > 0
1118
- ? slot.label
1119
- : formatMinuteOfDayLabel(minuteOfDay),
1120
- minuteOfDay,
1121
- durationMinutes: typeof slot.durationMinutes === "number" &&
1122
- Number.isFinite(slot.durationMinutes) &&
1123
- slot.durationMinutes > 0
1124
- ? slot.durationMinutes
1125
- : 45,
1126
- };
1127
- })
1128
- .filter((entry) => entry !== null);
1129
- if (slots.length > 0) {
1130
- return {
1131
- kind: "times_per_day",
1132
- slots,
1133
- visibilityLeadMinutes: typeof record.visibilityLeadMinutes === "number"
1134
- ? record.visibilityLeadMinutes
1135
- : 90,
1136
- visibilityLagMinutes: typeof record.visibilityLagMinutes === "number"
1137
- ? record.visibilityLagMinutes
1138
- : 180,
1139
- };
1140
- }
1141
- }
1142
- const count = typeof record.count === "number"
1143
- ? record.count
1144
- : typeof record.count === "string"
1145
- ? Number(record.count)
1146
- : NaN;
1147
- if (Number.isFinite(count) && count > 0) {
1148
- return {
1149
- kind: "times_per_day",
1150
- slots: buildDistributedDailySlots(count),
1151
- visibilityLeadMinutes: 90,
1152
- visibilityLagMinutes: 180,
1153
- };
1154
- }
1155
- }
1156
- if (cadenceKind === "daily") {
1157
- const windows = normalizeLifeWindows(record.windows ?? record.window);
1158
- if (windows.length > 0) {
1159
- return {
1160
- kind: "daily",
1161
- windows,
1162
- };
1163
- }
1164
- return {
1165
- kind: "daily",
1166
- windows: ["morning"],
1167
- };
1168
- }
1169
- return undefined;
1170
- }
1171
- /**
1172
- * Convert LLM-extracted params into a typed LifeOpsCadence.
1173
- * Returns null when the LLM output is insufficient to construct a
1174
- * valid cadence, letting the caller fall back to regex-derived values.
1175
- */
1176
- function buildCadenceFromLlmParams(params, context) {
1177
- const kind = params.cadenceKind;
1178
- if (!kind)
1179
- return null;
1180
- const effectiveTimeZone = context?.timeZone;
1181
- const timeOfDayMinute = typeof params.timeOfDay === "string"
1182
- ? parseTimeOfDayToken(params.timeOfDay)
1183
- : null;
1184
- const explicitSlots = typeof context?.intent === "string"
1185
- ? extractExplicitDailySlots(context.intent)
1186
- : [];
1187
- const slotDuration = typeof params.durationMinutes === "number" && params.durationMinutes > 0
1188
- ? params.durationMinutes
1189
- : 45;
1190
- const windows = (params.windows ?? []).filter((w) => w === "morning" || w === "afternoon" || w === "evening" || w === "night");
1191
- const effectiveWindows = windows.length > 0
1192
- ? windows
1193
- : timeOfDayMinute !== null
1194
- ? [inferWindowFromMinuteOfDay(timeOfDayMinute)]
1195
- : ["morning"];
1196
- if (kind === "once") {
1197
- if (timeOfDayMinute !== null) {
1198
- return {
1199
- cadence: {
1200
- kind: "once",
1201
- dueAt: buildOneOffDueAtFromMinuteOfDay({
1202
- minuteOfDay: timeOfDayMinute,
1203
- now: context?.now,
1204
- timeZone: effectiveTimeZone,
1205
- }),
1206
- },
1207
- };
1208
- }
1209
- return { cadence: { kind: "once", dueAt: new Date().toISOString() } };
1210
- }
1211
- if (kind === "daily") {
1212
- if (explicitSlots.length >= 2) {
1213
- return {
1214
- cadence: {
1215
- kind: "times_per_day",
1216
- slots: explicitSlots.map((slot) => ({
1217
- ...slot,
1218
- durationMinutes: slot.durationMinutes ?? slotDuration,
1219
- })),
1220
- visibilityLeadMinutes: 90,
1221
- visibilityLagMinutes: 180,
1222
- },
1223
- };
1224
- }
1225
- if (timeOfDayMinute !== null) {
1226
- return {
1227
- cadence: {
1228
- kind: "times_per_day",
1229
- slots: [buildSingleDailySlot(timeOfDayMinute, slotDuration)],
1230
- visibilityLeadMinutes: 90,
1231
- visibilityLagMinutes: 180,
1232
- },
1233
- };
1234
- }
1235
- if (effectiveWindows.length >= 2) {
1236
- return {
1237
- cadence: {
1238
- kind: "times_per_day",
1239
- slots: buildSlotsFromWindows(effectiveWindows),
1240
- visibilityLeadMinutes: 90,
1241
- visibilityLagMinutes: 180,
1242
- },
1243
- };
1244
- }
1245
- return { cadence: { kind: "daily", windows: effectiveWindows } };
1246
- }
1247
- if (kind === "weekly") {
1248
- const weekdays = params.weekdays;
1249
- if (!weekdays || weekdays.length === 0)
1250
- return null;
1251
- if (timeOfDayMinute !== null) {
1252
- return {
1253
- cadence: { kind: "weekly", weekdays, windows: ["custom"] },
1254
- windowPolicy: buildCustomTimeWindowPolicy(timeOfDayMinute, effectiveTimeZone ?? resolveDefaultTimeZone()),
1255
- };
1256
- }
1257
- return { cadence: { kind: "weekly", weekdays, windows: effectiveWindows } };
1258
- }
1259
- if (kind === "interval") {
1260
- const everyMinutes = params.everyMinutes;
1261
- if (!everyMinutes || everyMinutes <= 0)
1262
- return null;
1263
- return {
1264
- cadence: {
1265
- kind: "interval",
1266
- everyMinutes,
1267
- windows: effectiveWindows,
1268
- startMinuteOfDay: timeOfDayMinute ?? undefined,
1269
- durationMinutes: typeof params.durationMinutes === "number" &&
1270
- params.durationMinutes > 0
1271
- ? params.durationMinutes
1272
- : undefined,
1273
- },
1274
- };
1275
- }
1276
- if (kind === "times_per_day") {
1277
- if (explicitSlots.length >= 2) {
1278
- return {
1279
- cadence: {
1280
- kind: "times_per_day",
1281
- slots: explicitSlots.map((slot) => ({
1282
- ...slot,
1283
- durationMinutes: slot.durationMinutes ?? slotDuration,
1284
- })),
1285
- visibilityLeadMinutes: 90,
1286
- visibilityLagMinutes: 180,
1287
- },
1288
- };
1289
- }
1290
- if (timeOfDayMinute !== null) {
1291
- return {
1292
- cadence: {
1293
- kind: "times_per_day",
1294
- slots: [buildSingleDailySlot(timeOfDayMinute, slotDuration)],
1295
- visibilityLeadMinutes: 90,
1296
- visibilityLagMinutes: 180,
1297
- },
1298
- };
1299
- }
1300
- const count = params.timesPerDay;
1301
- if (!count || count <= 0)
1302
- return null;
1303
- return {
1304
- cadence: {
1305
- kind: "times_per_day",
1306
- slots: buildDistributedDailySlots(count).map((slot) => ({
1307
- ...slot,
1308
- durationMinutes: slotDuration,
1309
- })),
1310
- visibilityLeadMinutes: 90,
1311
- visibilityLagMinutes: 180,
1312
- },
1313
- };
1314
- }
1315
- return null;
1316
- }
1317
- function buildCadenceFromUpdateFields(args) {
1318
- const { currentCadence, currentWindowPolicy, timeZone, update } = args;
1319
- const kind = (update.cadenceKind ??
1320
- currentCadence.kind);
1321
- const requestedWindows = normalizeLifeWindows(update.windows ?? []);
1322
- const timeOfDayMinute = typeof update.timeOfDay === "string"
1323
- ? parseTimeOfDayToken(update.timeOfDay)
1324
- : null;
1325
- if (kind === "interval") {
1326
- const everyMinutes = update.everyMinutes ??
1327
- (currentCadence.kind === "interval" ? currentCadence.everyMinutes : null);
1328
- if (!everyMinutes || everyMinutes <= 0) {
1329
- return null;
1330
- }
1331
- const windows = requestedWindows.length > 0
1332
- ? requestedWindows
1333
- : currentCadence.kind === "interval" &&
1334
- currentCadence.windows.length > 0
1335
- ? normalizeLifeWindows(currentCadence.windows)
1336
- : timeOfDayMinute !== null
1337
- ? [inferWindowFromMinuteOfDay(timeOfDayMinute)]
1338
- : ["morning"];
1339
- return {
1340
- cadence: {
1341
- kind: "interval",
1342
- everyMinutes,
1343
- windows,
1344
- startMinuteOfDay: timeOfDayMinute ??
1345
- (currentCadence.kind === "interval"
1346
- ? currentCadence.startMinuteOfDay
1347
- : undefined),
1348
- maxOccurrencesPerDay: currentCadence.kind === "interval"
1349
- ? currentCadence.maxOccurrencesPerDay
1350
- : undefined,
1351
- durationMinutes: currentCadence.kind === "interval"
1352
- ? currentCadence.durationMinutes
1353
- : undefined,
1354
- visibilityLeadMinutes: currentCadence.kind === "interval"
1355
- ? currentCadence.visibilityLeadMinutes
1356
- : undefined,
1357
- visibilityLagMinutes: currentCadence.kind === "interval"
1358
- ? currentCadence.visibilityLagMinutes
1359
- : undefined,
1360
- },
1361
- };
1362
- }
1363
- if (kind === "weekly") {
1364
- const weekdays = update.weekdays ??
1365
- (currentCadence.kind === "weekly" ? currentCadence.weekdays : null);
1366
- if (!weekdays || weekdays.length === 0) {
1367
- return null;
1368
- }
1369
- if (timeOfDayMinute !== null) {
1370
- return {
1371
- cadence: {
1372
- kind: "weekly",
1373
- weekdays,
1374
- windows: ["custom"],
1375
- visibilityLeadMinutes: currentCadence.kind === "weekly"
1376
- ? currentCadence.visibilityLeadMinutes
1377
- : undefined,
1378
- visibilityLagMinutes: currentCadence.kind === "weekly"
1379
- ? currentCadence.visibilityLagMinutes
1380
- : undefined,
1381
- },
1382
- windowPolicy: buildCustomTimeWindowPolicy(timeOfDayMinute, timeZone),
1383
- };
1384
- }
1385
- return {
1386
- cadence: {
1387
- kind: "weekly",
1388
- weekdays,
1389
- windows: requestedWindows.length > 0
1390
- ? requestedWindows
1391
- : currentCadence.kind === "weekly" &&
1392
- currentCadence.windows.length > 0
1393
- ? currentCadence.windows
1394
- : ["morning"],
1395
- visibilityLeadMinutes: currentCadence.kind === "weekly"
1396
- ? currentCadence.visibilityLeadMinutes
1397
- : undefined,
1398
- visibilityLagMinutes: currentCadence.kind === "weekly"
1399
- ? currentCadence.visibilityLagMinutes
1400
- : undefined,
1401
- },
1402
- windowPolicy: currentWindowPolicy.windows.some((window) => (requestedWindows.length > 0
1403
- ? requestedWindows
1404
- : ["morning"]).includes(window.name))
1405
- ? undefined
1406
- : resolveDefaultWindowPolicy(timeZone),
1407
- };
1408
- }
1409
- if (kind === "daily") {
1410
- if (timeOfDayMinute !== null) {
1411
- return {
1412
- cadence: {
1413
- kind: "times_per_day",
1414
- slots: [buildSingleDailySlot(timeOfDayMinute)],
1415
- visibilityLeadMinutes: 90,
1416
- visibilityLagMinutes: 180,
1417
- },
1418
- };
1419
- }
1420
- return {
1421
- cadence: {
1422
- kind: "daily",
1423
- windows: requestedWindows.length > 0
1424
- ? requestedWindows
1425
- : currentCadence.kind === "daily" &&
1426
- currentCadence.windows.length > 0
1427
- ? currentCadence.windows
1428
- : ["morning"],
1429
- visibilityLeadMinutes: currentCadence.kind === "daily"
1430
- ? currentCadence.visibilityLeadMinutes
1431
- : undefined,
1432
- visibilityLagMinutes: currentCadence.kind === "daily"
1433
- ? currentCadence.visibilityLagMinutes
1434
- : undefined,
1435
- },
1436
- };
1437
- }
1438
- if (kind === "times_per_day") {
1439
- if (timeOfDayMinute !== null) {
1440
- return {
1441
- cadence: {
1442
- kind: "times_per_day",
1443
- slots: [buildSingleDailySlot(timeOfDayMinute)],
1444
- visibilityLeadMinutes: 90,
1445
- visibilityLagMinutes: 180,
1446
- },
1447
- };
1448
- }
1449
- if (requestedWindows.length > 0) {
1450
- return {
1451
- cadence: {
1452
- kind: "times_per_day",
1453
- slots: buildSlotsFromWindows(requestedWindows),
1454
- visibilityLeadMinutes: 90,
1455
- visibilityLagMinutes: 180,
1456
- },
1457
- };
1458
- }
1459
- return currentCadence.kind === "times_per_day"
1460
- ? { cadence: currentCadence }
1461
- : null;
1462
- }
1463
- return currentCadence.kind === "once" ? { cadence: currentCadence } : null;
1464
- }
1465
- function hasDefinitionUpdateChanges(request) {
1466
- return (request.title != null ||
1467
- request.cadence != null ||
1468
- request.priority != null ||
1469
- request.description != null ||
1470
- request.windowPolicy != null ||
1471
- request.reminderPlan != null);
1472
- }
1473
- function buildDefaultReminderPlan(label) {
1474
- return {
1475
- steps: [{ channel: "in_app", offsetMinutes: 0, label }],
1476
- };
1477
- }
1478
- function scoreDefinitionTitleQuality(value) {
1479
- const normalized = normalizeTitle(value ?? "");
1480
- if (!normalized) {
1481
- return Number.NEGATIVE_INFINITY;
1482
- }
1483
- let score = normalized.split(/\s+/).filter(Boolean).length;
1484
- if (/\b\d+\b/.test(normalized)) {
1485
- score += 6;
1486
- }
1487
- if (/[+&]/.test(value ?? "") || /\band\b/.test(normalized)) {
1488
- score += 4;
1489
- }
1490
- if (/^(?:do|work out|workout|habit|routine|task|todo|reminder|alarm)\b/.test(normalized)) {
1491
- score -= 5;
1492
- }
1493
- if (GENERIC_DERIVED_TITLE_RE.test(normalized)) {
1494
- score -= 6;
1495
- }
1496
- return score;
1497
- }
1498
- function shouldAdoptPlannerTitle(args) {
1499
- const plannerTitle = args.plannerTitle?.trim();
1500
- if (!plannerTitle) {
1501
- return false;
1502
- }
1503
- const currentTitle = args.currentTitle?.trim();
1504
- if (!currentTitle) {
1505
- return true;
1506
- }
1507
- if (normalizeTitle(currentTitle) === normalizeTitle(plannerTitle)) {
1508
- return false;
1509
- }
1510
- return (scoreDefinitionTitleQuality(plannerTitle) >
1511
- scoreDefinitionTitleQuality(currentTitle));
1512
- }
1513
- function shouldAdoptPlannerCadence(args) {
1514
- const { currentCadence, plannerCadence } = args;
1515
- if (!currentCadence) {
1516
- return true;
1517
- }
1518
- if (currentCadence.kind === "times_per_day") {
1519
- return ((plannerCadence.kind === "times_per_day" &&
1520
- plannerCadence.slots.length >= currentCadence.slots.length) ||
1521
- (plannerCadence.kind === "once" && currentCadence.slots.length === 1));
1522
- }
1523
- if (currentCadence.kind === "weekly") {
1524
- return (plannerCadence.kind === "weekly" &&
1525
- plannerCadence.weekdays.length >= currentCadence.weekdays.length &&
1526
- (currentCadence.windows.includes("custom")
1527
- ? plannerCadence.windows.includes("custom")
1528
- : plannerCadence.windows.length >= currentCadence.windows.length));
1529
- }
1530
- if (currentCadence.kind === "interval") {
1531
- return plannerCadence.kind === "interval";
1532
- }
1533
- if (currentCadence.kind === "once") {
1534
- return plannerCadence.kind === "once";
1535
- }
1536
- if (currentCadence.kind === "daily") {
1537
- return (plannerCadence.kind === "times_per_day" ||
1538
- (plannerCadence.kind === "daily" &&
1539
- plannerCadence.windows.length >= currentCadence.windows.length));
1540
- }
1541
- return true;
1542
- }
1543
- function shouldRequireLifeCreateConfirmation(args) {
1544
- if (args.messageSource === "autonomy") {
1545
- return false;
1546
- }
1547
- if (args.requestKind && args.cadence?.kind === "once") {
1548
- return false;
1549
- }
1550
- return !args.confirmed;
1551
- }
1552
- function describeReminderIntensity(intensity) {
1553
- switch (intensity) {
1554
- case "minimal":
1555
- return "minimal";
1556
- case "normal":
1557
- return "normal";
1558
- case "persistent":
1559
- return "persistent";
1560
- case "high_priority_only":
1561
- return "high priority only";
1562
- }
1563
- return "normal";
1564
- }
1565
- function formatGoalExperienceLoopSummary(experienceLoop) {
1566
- if (!experienceLoop || !experienceLoop.summary) {
1567
- return null;
1568
- }
1569
- const similarGoalTitle = experienceLoop.similarGoals?.[0]?.title?.trim();
1570
- const carryForwardTitle = experienceLoop.suggestedCarryForward?.[0]?.title?.trim();
1571
- const parts = [experienceLoop.summary.trim()];
1572
- if (similarGoalTitle) {
1573
- parts.push(`Closest match: "${similarGoalTitle}".`);
1574
- }
1575
- if (carryForwardTitle) {
1576
- parts.push(`Carry forward "${carryForwardTitle}" if it still fits.`);
1577
- }
1578
- return parts.join(" ");
1579
- }
1580
- function formatWeeklyGoalReview(args) {
1581
- const parts = [
1582
- `Weekly goal review: ${args.summary.totalGoals} active ${args.summary.totalGoals === 1 ? "goal" : "goals"}, ${args.summary.onTrackCount} on track, ${args.summary.atRiskCount} at risk, ${args.summary.needsAttentionCount} needing attention.`,
1583
- ];
1584
- if (args.atRisk.length > 0) {
1585
- parts.push(`Drifting: ${args.atRisk.slice(0, 3).map((review) => review.goal.title).join(", ")}.`);
1586
- }
1587
- if (args.needsAttention.length > 0) {
1588
- parts.push(`Needs attention: ${args.needsAttention
1589
- .slice(0, 3)
1590
- .map((review) => review.goal.title)
1591
- .join(", ")}.`);
1592
- }
1593
- if (args.onTrack.length > 0) {
1594
- parts.push(`On track: ${args.onTrack
1595
- .slice(0, 3)
1596
- .map((review) => review.goal.title)
1597
- .join(", ")}.`);
1598
- }
1599
- return parts.join(" ");
1600
- }
1601
- // ── Main action ───────────────────────────────────────
1602
- export const lifeAction = {
1603
- name: "LIFE",
1604
- // CREATE_TASK and COMPLETE_TASK must NOT appear in similes: they are
1605
- // the orchestrator's primary aliases, and the collision routes coding
1606
- // prompts ("fix this bug") here by name match. LifeOps intent is still
1607
- // covered by the todo/habit/goal/reminder similes plus description.
1608
- similes: [
1609
- "MANAGE_LIFEOPS",
1610
- "QUERY_LIFEOPS",
1611
- "CREATE_TODO",
1612
- "ADD_TODO",
1613
- "LIST_TODOS",
1614
- "TODO_LIST",
1615
- "COMPLETE_TODO",
1616
- "CREATE_HABIT",
1617
- "CREATE_GOAL",
1618
- "LIFE_CREATE_DEFINITION",
1619
- "TRACK_HABIT",
1620
- "SET_ALARM",
1621
- "SET_REMINDER",
1622
- "SNOOZE_REMINDER",
1623
- "SET_REMINDER_INTENSITY",
1624
- ],
1625
- description: "Manage the user's personal routines, habits, goals, reminders, alarms, and escalation settings through LifeOps. " +
1626
- "USE this action for: creating, editing, or deleting tasks, habits, routines, and goals; " +
1627
- "todo and goal requests like 'add a todo: pick up dry cleaning tomorrow', 'remember to call mom on Sunday', 'what's on my todo list today?', or 'set a goal to save $5,000 by the end of the year'; " +
1628
- "setting one-off alarms or wake-up reminders like 'set an alarm for 7am' or 'wake me up at 7'; " +
1629
- "helping the user actually set up follow-through when they say things like 'help me brush my teeth every day', 'i keep forgetting x', or 'help me actually do it'; " +
1630
- "using LifeOps defaults for common routines when the user gives a natural window instead of an exact clock, like water reminders, stretch breaks, weekday-after-lunch Invisalign checks, twice-weekly shave reminders, or brushing when they wake up and before bed; " +
1631
- "marking items as complete, skipping, or snoozing them; reviewing goal progress, weekly goal review, and carry-forward lessons from similar completed goals; " +
1632
- "setting up phone/SMS escalation channels; adjusting reminder frequency or intensity; " +
1633
- "querying an overview of active LifeOps items. " +
1634
- "These are executable LifeOps items, not profile facts or bio updates. " +
1635
- "ALWAYS use LIFE for dynamic status questions like 'what's still left for today', 'what do i still need to do today', or 'anything else in my LifeOps list', even when the conversation already mentioned tasks, because their status may have changed after a completion, snooze, or reminder. " +
1636
- "Use LIFE for reminder/escalation policies about the owner's own follow-through, such as 'if I still haven't answered about those three events, bump me again with context instead of starting over,' when the request is about reminding the owner rather than modifying the calendar itself. " +
1637
- "Do not fall back to REPLY, UPDATE_ENTITY, or UPDATE_OWNER_PROFILE when the user is asking to create or inspect a todo, habit, goal, reminder, or alarm. " +
1638
- "DO NOT use this action for generic coaching or advice questions like 'any tips on setting better goals?' unless the user is also asking you to create, update, review, or track a concrete goal, task, reminder, or routine. " +
1639
- "DO NOT use this action for person-specific follow-ups like 'remind me to follow up with David next week about the project' — use OWNER_RELATIONSHIP instead. " +
1640
- "DO NOT use this action for Gmail inbox triage, email search, drafting or sending emails — use OWNER_INBOX with channel=gmail instead. " +
1641
- "DO NOT use this action for daily briefs, unread summaries, drafts awaiting sign-off, or cross-channel inbox review — use OWNER_INBOX instead. " +
1642
- "DO NOT use this action for calendar lookups, scheduling meetings, availability, Calendly, or travel itineraries — use OWNER_CALENDAR instead. " +
1643
- "DO NOT use this action for multi-device push ladders or device-wide reminder delivery — use PUBLISH_DEVICE_INTENT instead. " +
1644
- "DO NOT use this action for pre-event asset checklists, questions like 'what slides, bio, title, or portal assets do I still owe before the event', document-signing workflows, collecting updated ID copies, or cancellation-fee warning/escalation policies — use OWNER_INBOX, PUBLISH_DEVICE_INTENT, OWNER_CALENDAR, or LIFEOPS_COMPUTER_USE instead. " +
1645
- "DO NOT use this action for browser/portal/file workflows on the owner's machine — use LIFEOPS_COMPUTER_USE instead. " +
1646
- "This action provides the final grounded reply; do not pair it with a speculative REPLY action or fall back to advice-only chat when the user wants real LifeOps follow-through.",
1647
- descriptionCompressed: "LifeOps: manage habits, goals, reminders, alarms, escalation. Create/edit/complete/snooze items. Query active status.",
1648
- suppressPostActionContinuation: true,
1649
- validate: async (runtime, message) => {
1650
- // Coding prompts share LifeOps verbs ("make", "create", "add") so
1651
- // the action selector can still pick LIFE. Decline here to let
1652
- // plugin-agent-orchestrator's CREATE_TASK take the route.
1653
- if (looksLikeCodingTaskRequest(messageText(message))) {
1654
- return false;
1655
- }
1656
- return hasLifeOpsAccess(runtime, message);
1657
- },
1658
- handler: async (runtime, message, state, options) => {
1659
- if (!(await hasLifeOpsAccess(runtime, message))) {
1660
- const fallback = "Life management is restricted to the owner, explicitly granted users, and the agent.";
1661
- return {
1662
- success: false,
1663
- text: await renderLifeActionReply({
1664
- runtime,
1665
- message,
1666
- state,
1667
- intent: normalizeLifeInputText(messageText(message)),
1668
- scenario: "reply_only",
1669
- fallback,
1670
- context: {
1671
- reason: "access_restricted",
1672
- },
1673
- }),
1674
- };
1675
- }
1676
- const rawParams = options?.parameters;
1677
- const params = rawParams ?? {};
1678
- const currentText = normalizeLifeInputText(messageText(message));
1679
- const details = params.details;
1680
- const deferredDraft = latestDeferredLifeDraft(state);
1681
- const turnsSinceDraft = deferredDraft != null
1682
- ? (countTurnsSinceLatestDeferredLifeDraft(state) ?? 0) + 1
1683
- : undefined;
1684
- const deferredDraftFollowupMode = deferredDraft
1685
- ? await extractDeferredLifeDraftFollowupWithLlm({
1686
- runtime,
1687
- message,
1688
- state,
1689
- currentText,
1690
- draft: deferredDraft,
1691
- })
1692
- : null;
1693
- const draftExpiryReason = deferredLifeDraftExpiryReason({
1694
- draft: deferredDraft,
1695
- turnsSinceDraft,
1696
- });
1697
- if (draftExpiryReason && deferredDraftFollowupMode === "confirm") {
1698
- const fallback = "That LifeOps draft expired. Please restate it and I'll preview it again.";
1699
- return {
1700
- success: false,
1701
- text: await renderLifeActionReply({
1702
- runtime,
1703
- message,
1704
- state,
1705
- intent: currentText,
1706
- scenario: "reply_only",
1707
- fallback,
1708
- context: {
1709
- reason: "draft_expired",
1710
- },
1711
- }),
1712
- };
1713
- }
1714
- if (deferredDraftFollowupMode === "cancel") {
1715
- const fallback = "Okay, I won't save it yet.";
1716
- return {
1717
- success: true,
1718
- text: await renderLifeActionReply({
1719
- runtime,
1720
- message,
1721
- state,
1722
- intent: currentText,
1723
- scenario: "reply_only",
1724
- fallback,
1725
- context: {
1726
- reason: "draft_cancelled",
1727
- draft: deferredDraft
1728
- ? {
1729
- operation: deferredDraft.operation,
1730
- title: deferredDraft.request.title,
1731
- }
1732
- : null,
1733
- },
1734
- }),
1735
- data: {
1736
- actionName: "LIFE",
1737
- noop: true,
1738
- },
1739
- };
1740
- }
1741
- const deferredDraftReuseMode = resolveDeferredLifeDraftReuseMode({
1742
- details,
1743
- draft: deferredDraft,
1744
- explicitAction: params.action,
1745
- llmMode: deferredDraftFollowupMode,
1746
- turnsSinceDraft,
1747
- });
1748
- const reuseDeferredDraft = deferredDraftReuseMode !== null;
1749
- const intent = reuseDeferredDraft
1750
- ? deferredDraftReuseMode === "confirm"
1751
- ? normalizeLifeInputText(deferredDraft?.intent ?? "")
1752
- : normalizeLifeInputText(params.intent?.trim() ?? currentText)
1753
- : normalizeLifeInputText(params.intent?.trim() ?? currentText);
1754
- if (!intent) {
1755
- const fallback = "Tell me what you want me to do.";
1756
- return {
1757
- success: false,
1758
- text: await renderLifeActionReply({
1759
- runtime,
1760
- message,
1761
- state,
1762
- intent: currentText,
1763
- scenario: "reply_only",
1764
- fallback,
1765
- context: {
1766
- reason: "missing_intent",
1767
- },
1768
- }),
1769
- };
1770
- }
1771
- const explicitOperation = params.action
1772
- ? ACTION_TO_OPERATION[params.action]
1773
- : undefined;
1774
- const operationPlan = reuseDeferredDraft && deferredDraft
1775
- ? {
1776
- confidence: 1,
1777
- missing: [],
1778
- operation: deferredDraft.operation,
1779
- shouldAct: true,
1780
- }
1781
- : await resolveLifeOperationPlan({
1782
- runtime,
1783
- message,
1784
- state,
1785
- intent,
1786
- explicitOperation,
1787
- });
1788
- const forceCreateExecution = shouldForceLifeCreateExecution({
1789
- intent,
1790
- missing: operationPlan.missing,
1791
- operation: operationPlan.operation,
1792
- details,
1793
- title: params.title,
1794
- });
1795
- if (!operationPlan.shouldAct && !forceCreateExecution) {
1796
- const fallback = buildLifeClarificationFallback({
1797
- missing: operationPlan.missing,
1798
- operation: operationPlan.operation,
1799
- });
1800
- return {
1801
- success: true,
1802
- text: await renderLifeActionReply({
1803
- runtime,
1804
- message,
1805
- state,
1806
- intent,
1807
- scenario: operationPlan.operation === "create_goal"
1808
- ? "clarify_create_goal"
1809
- : "clarify_create_definition",
1810
- fallback,
1811
- context: {
1812
- missing: operationPlan.missing,
1813
- operation: operationPlan.operation,
1814
- },
1815
- }),
1816
- data: {
1817
- actionName: "LIFE",
1818
- noop: true,
1819
- suggestedOperation: operationPlan.operation,
1820
- },
1821
- };
1822
- }
1823
- const operation = forceCreateExecution
1824
- ? "create_definition"
1825
- : operationPlan.operation;
1826
- if (!operation) {
1827
- const fallback = "Tell me what LifeOps action you want me to take.";
1828
- return {
1829
- success: true,
1830
- text: await renderLifeActionReply({
1831
- runtime,
1832
- message,
1833
- state,
1834
- intent,
1835
- scenario: "reply_only",
1836
- fallback,
1837
- context: {
1838
- reason: "missing_operation_after_extraction",
1839
- },
1840
- }),
1841
- data: {
1842
- actionName: "LIFE",
1843
- noop: true,
1844
- },
1845
- };
1846
- }
1847
- const service = new LifeOpsService(runtime);
1848
- const domain = detailString(details, "domain");
1849
- const ownership = requestedOwnership(domain);
1850
- const chatText = intent;
1851
- const targetName = params.target ?? params.title;
1852
- const createConfirmed = deferredDraftReuseMode === "confirm" ||
1853
- detailBoolean(details, "confirmed") === true;
1854
- try {
1855
- const createDefinition = async () => {
1856
- const deferredDefinitionDraft = reuseDeferredDraft && deferredDraft?.operation === "create_definition"
1857
- ? deferredDraft
1858
- : null;
1859
- const editingDeferredDefinitionDraft = deferredDraftReuseMode === "edit" &&
1860
- deferredDefinitionDraft?.operation === "create_definition";
1861
- const explicitCadenceDetail = normalizeCadenceDetail(detailObject(details, "cadence"));
1862
- const fallbackTitle = deferredDefinitionDraft?.request.title ?? null;
1863
- let title = editingDeferredDefinitionDraft
1864
- ? (params.title ?? fallbackTitle)
1865
- : (fallbackTitle ?? params.title ?? null);
1866
- const fallbackCadence = deferredDefinitionDraft?.request.cadence;
1867
- let cadence = editingDeferredDefinitionDraft
1868
- ? (explicitCadenceDetail ?? fallbackCadence ?? undefined)
1869
- : (fallbackCadence ?? explicitCadenceDetail ?? undefined);
1870
- let windowPolicy = editingDeferredDefinitionDraft
1871
- ? (detailObject(details, "windowPolicy") ?? deferredDefinitionDraft?.request.windowPolicy)
1872
- : (deferredDefinitionDraft?.request.windowPolicy ??
1873
- detailObject(details, "windowPolicy"));
1874
- const explicitPriority = detailNumber(details, "priority");
1875
- const explicitDescription = detailString(details, "description");
1876
- const explicitMetadata = detailObject(details, "metadata");
1877
- // Track whether cadence/title came from explicit high-confidence
1878
- // sources so the planner only fills genuine gaps.
1879
- const hadExplicitCadence = Boolean((editingDeferredDefinitionDraft
1880
- ? (explicitCadenceDetail ??
1881
- deferredDefinitionDraft?.request.cadence)
1882
- : deferredDefinitionDraft?.request.cadence) ??
1883
- explicitCadenceDetail);
1884
- const hadExplicitTitle = Boolean((editingDeferredDefinitionDraft
1885
- ? params.title
1886
- : deferredDefinitionDraft?.request.title) ?? params.title);
1887
- // ── LLM parameter enhancement (fills gaps) ────────
1888
- // Skip when reusing a confirmed deferred draft — the user already
1889
- // approved those values.
1890
- let llmPlan = null;
1891
- let llmDescription;
1892
- let llmPriority;
1893
- let llmRequestKind = null;
1894
- if (!deferredDefinitionDraft || editingDeferredDefinitionDraft) {
1895
- llmPlan = await extractTaskCreatePlanWithLlm({
1896
- runtime,
1897
- intent,
1898
- state: state ?? undefined,
1899
- message: message ?? undefined,
1900
- });
1901
- const shouldHonorPlannerResponse = llmPlan?.mode === "respond" &&
1902
- Boolean(llmPlan.response) &&
1903
- !editingDeferredDefinitionDraft &&
1904
- !params.title &&
1905
- !explicitCadenceDetail &&
1906
- !detailString(details, "description") &&
1907
- !detailString(details, "goalId") &&
1908
- !detailString(details, "goalTitle") &&
1909
- !detailString(details, "kind");
1910
- if (shouldHonorPlannerResponse && llmPlan?.response) {
1911
- return {
1912
- success: true,
1913
- text: llmPlan.response,
1914
- };
1915
- }
1916
- if (llmPlan) {
1917
- llmRequestKind = llmPlan.requestKind;
1918
- if (!hadExplicitTitle &&
1919
- shouldAdoptPlannerTitle({
1920
- currentTitle: title,
1921
- plannerTitle: llmPlan.title,
1922
- })) {
1923
- title = llmPlan.title;
1924
- }
1925
- if ((editingDeferredDefinitionDraft || !hadExplicitCadence) &&
1926
- llmPlan.cadenceKind) {
1927
- const llmCadenceTimeZone = normalizeLifeTimeZoneToken(detailString(details, "timeZone") ??
1928
- llmPlan.timeZone ??
1929
- deferredDefinitionDraft?.request.timezone ??
1930
- windowPolicy?.timezone);
1931
- const llmCadence = buildCadenceFromLlmParams(llmPlan, {
1932
- intent,
1933
- timeZone: llmCadenceTimeZone ?? undefined,
1934
- });
1935
- if (llmCadence &&
1936
- shouldAdoptPlannerCadence({
1937
- currentCadence: cadence,
1938
- plannerCadence: llmCadence.cadence,
1939
- })) {
1940
- cadence = llmCadence.cadence;
1941
- windowPolicy = llmCadence.windowPolicy ?? windowPolicy;
1942
- }
1943
- }
1944
- if (!explicitDescription && llmPlan.description) {
1945
- llmDescription = llmPlan.description;
1946
- }
1947
- if (explicitPriority === undefined && llmPlan.priority) {
1948
- llmPriority = llmPlan.priority;
1949
- }
1950
- }
1951
- }
1952
- const resolvedTimeZone = normalizeLifeTimeZoneToken(detailString(details, "timeZone") ??
1953
- llmPlan?.timeZone ??
1954
- deferredDefinitionDraft?.request.timezone ??
1955
- windowPolicy?.timezone);
1956
- const timedRequestKind = llmRequestKind;
1957
- const nativeAppleMetadata = timedRequestKind && cadence?.kind === "once"
1958
- ? buildNativeAppleReminderMetadata({
1959
- kind: timedRequestKind,
1960
- source: "llm",
1961
- })
1962
- : undefined;
1963
- const definitionMetadata = editingDeferredDefinitionDraft
1964
- ? mergeMetadataRecords(deferredDefinitionDraft?.request.metadata, mergeMetadataRecords(explicitMetadata, nativeAppleMetadata))
1965
- : (deferredDefinitionDraft?.request.metadata ??
1966
- mergeMetadataRecords(explicitMetadata, nativeAppleMetadata));
1967
- if (!title) {
1968
- const fallback = "What should I call it?";
1969
- return {
1970
- success: false,
1971
- text: await renderLifeActionReply({
1972
- runtime,
1973
- message,
1974
- state,
1975
- intent,
1976
- scenario: "clarify_create_definition",
1977
- fallback,
1978
- context: {
1979
- missing: ["title"],
1980
- operation: "create_definition",
1981
- },
1982
- }),
1983
- };
1984
- }
1985
- if (!cadence) {
1986
- const fallback = "When should it happen?";
1987
- return {
1988
- success: false,
1989
- text: await renderLifeActionReply({
1990
- runtime,
1991
- message,
1992
- state,
1993
- intent,
1994
- scenario: "clarify_create_definition",
1995
- fallback,
1996
- context: {
1997
- missing: ["schedule"],
1998
- operation: "create_definition",
1999
- },
2000
- }),
2001
- };
2002
- }
2003
- const kind = (editingDeferredDefinitionDraft
2004
- ? detailString(details, "kind")
2005
- : deferredDefinitionDraft?.request.kind) ??
2006
- detailString(details, "kind") ??
2007
- "habit";
2008
- const definitionDraft = {
2009
- intent,
2010
- operation: "create_definition",
2011
- createdAt: editingDeferredDefinitionDraft
2012
- ? Date.now()
2013
- : (deferredDefinitionDraft?.createdAt ?? Date.now()),
2014
- request: {
2015
- cadence,
2016
- description: explicitDescription ??
2017
- llmDescription ??
2018
- (editingDeferredDefinitionDraft
2019
- ? deferredDefinitionDraft?.request.description
2020
- : undefined),
2021
- goalRef: detailString(details, "goalId") ??
2022
- detailString(details, "goalTitle") ??
2023
- deferredDefinitionDraft?.request.goalRef ??
2024
- undefined,
2025
- kind,
2026
- priority: explicitPriority ??
2027
- llmPriority ??
2028
- deferredDefinitionDraft?.request.priority,
2029
- progressionRule: detailObject(details, "progressionRule") ??
2030
- deferredDefinitionDraft?.request.progressionRule,
2031
- reminderPlan: detailObject(details, "reminderPlan") ??
2032
- deferredDefinitionDraft?.request.reminderPlan ??
2033
- buildDefaultReminderPlan(`${title} reminder`),
2034
- timezone: normalizeLifeTimeZoneToken(llmPlan?.timeZone) ??
2035
- normalizeLifeTimeZoneToken(resolvedTimeZone ?? deferredDefinitionDraft?.request.timezone) ??
2036
- resolvedTimeZone ??
2037
- deferredDefinitionDraft?.request.timezone,
2038
- title,
2039
- metadata: definitionMetadata,
2040
- windowPolicy,
2041
- websiteAccess: detailObject(details, "websiteAccess") ?? deferredDefinitionDraft?.request.websiteAccess,
2042
- },
2043
- };
2044
- if (shouldRequireLifeCreateConfirmation({
2045
- confirmed: createConfirmed,
2046
- messageSource: typeof message.content?.source === "string"
2047
- ? message.content.source
2048
- : undefined,
2049
- requestKind: timedRequestKind,
2050
- cadence: definitionDraft.request.cadence,
2051
- })) {
2052
- const fallback = `I can save this as a ${definitionDraft.request.kind} named "${definitionDraft.request.title}" that happens ${summarizeCadence(definitionDraft.request.cadence)}. Confirm and I'll save it, or tell me what to change.`;
2053
- return {
2054
- success: true,
2055
- text: await renderLifeActionReply({
2056
- runtime,
2057
- message,
2058
- state,
2059
- intent,
2060
- scenario: "preview_definition",
2061
- fallback,
2062
- context: {
2063
- draft: definitionDraft.request,
2064
- requestKind: timedRequestKind,
2065
- },
2066
- }),
2067
- data: {
2068
- actionName: "LIFE",
2069
- deferred: true,
2070
- lifeDraft: definitionDraft,
2071
- preview: {
2072
- cadence: definitionDraft.request.cadence,
2073
- kind: definitionDraft.request.kind,
2074
- title: definitionDraft.request.title,
2075
- },
2076
- },
2077
- };
2078
- }
2079
- const resolvedGoal = definitionDraft.request.goalRef
2080
- ? await resolveGoal(service, definitionDraft.request.goalRef, domain)
2081
- : null;
2082
- const created = await service.createDefinition({
2083
- ownership,
2084
- kind: definitionDraft.request.kind,
2085
- title: definitionDraft.request.title,
2086
- description: definitionDraft.request.description,
2087
- originalIntent: definitionDraft.intent || definitionDraft.request.title,
2088
- cadence: definitionDraft.request.cadence,
2089
- timezone: normalizeLifeTimeZoneToken(definitionDraft.request.timezone) ??
2090
- definitionDraft.request.timezone,
2091
- priority: definitionDraft.request.priority,
2092
- windowPolicy: definitionDraft.request.windowPolicy,
2093
- progressionRule: definitionDraft.request.progressionRule,
2094
- reminderPlan: definitionDraft.request.reminderPlan,
2095
- metadata: definitionDraft.request.metadata,
2096
- websiteAccess: definitionDraft.request.websiteAccess,
2097
- goalId: resolvedGoal?.goal.id ?? null,
2098
- source: "chat",
2099
- });
2100
- const fallback = `Saved "${created.definition.title}" as ${summarizeCadence(created.definition.cadence)}.`;
2101
- return {
2102
- success: true,
2103
- text: await renderLifeActionReply({
2104
- runtime,
2105
- message,
2106
- state,
2107
- intent,
2108
- scenario: "saved_definition",
2109
- fallback,
2110
- context: {
2111
- created: {
2112
- title: created.definition.title,
2113
- cadence: created.definition.cadence,
2114
- },
2115
- requestKind: timedRequestKind,
2116
- },
2117
- }),
2118
- data: toActionData(created),
2119
- };
2120
- };
2121
- // ── Queries ─────────────────────────────────────
2122
- if (operation === "query_calendar_today" ||
2123
- operation === "query_calendar_next") {
2124
- const google = await getGoogleCapabilityStatus(service);
2125
- if (!google.hasCalendarRead) {
2126
- return {
2127
- success: false,
2128
- text: calendarReadUnavailableMessage(google),
2129
- };
2130
- }
2131
- if (operation === "query_calendar_next") {
2132
- const ctx = await service.getNextCalendarEventContext(INTERNAL_URL);
2133
- return {
2134
- success: true,
2135
- text: formatNextEventContext(ctx),
2136
- data: toActionData(ctx),
2137
- };
2138
- }
2139
- // The planner extracts the time window as a structured `when` param
2140
- // ("today" | "tomorrow" | "this_week"), so we never re-parse the
2141
- // free-form `intent` string at runtime. Default to "today" when the
2142
- // caller omits it.
2143
- const whenRaw = detailString(details, "when")?.toLowerCase().trim();
2144
- const when = whenRaw === "tomorrow"
2145
- ? "tomorrow"
2146
- : whenRaw === "this_week" || whenRaw === "this week" || whenRaw === "week"
2147
- ? "this_week"
2148
- : "today";
2149
- const range = when === "tomorrow"
2150
- ? dayRange(1)
2151
- : when === "this_week"
2152
- ? weekRange()
2153
- : dayRange(0);
2154
- const label = when === "tomorrow"
2155
- ? "tomorrow"
2156
- : when === "this_week"
2157
- ? "this week"
2158
- : "today";
2159
- const feed = await service.getCalendarFeed(INTERNAL_URL, {
2160
- includeHiddenCalendars: true,
2161
- timeMin: range.timeMin,
2162
- timeMax: range.timeMax,
2163
- });
2164
- return {
2165
- success: true,
2166
- text: formatCalendarFeed(feed, label),
2167
- data: toActionData(feed),
2168
- };
2169
- }
2170
- if (operation === "query_email") {
2171
- const limit = detailNumber(details, "limit") ?? 10;
2172
- return ((await gmailAction.handler?.(runtime, message, state, {
2173
- parameters: {
2174
- subaction: "triage",
2175
- intent,
2176
- details: {
2177
- ...details,
2178
- maxResults: limit,
2179
- },
2180
- },
2181
- })) ?? {
2182
- success: false,
2183
- text: "I couldn't route that Gmail request yet.",
2184
- });
2185
- }
2186
- if (operation === "query_overview") {
2187
- const overview = await service.getOverview();
2188
- const userQuery = messageText(message) || intent || "overview";
2189
- const fallback = formatOverviewForQuery(overview, userQuery);
2190
- return {
2191
- success: true,
2192
- text: await renderLifeActionReply({
2193
- runtime,
2194
- message,
2195
- state,
2196
- intent: userQuery,
2197
- scenario: "overview",
2198
- fallback,
2199
- context: {
2200
- summary: overview.owner.summary,
2201
- occurrenceTitles: overview.owner.occurrences
2202
- .slice(0, 6)
2203
- .map((occurrence) => occurrence.title),
2204
- goalTitles: overview.owner.goals
2205
- .slice(0, 3)
2206
- .map((goal) => goal.title),
2207
- },
2208
- }),
2209
- data: toActionData(overview),
2210
- };
2211
- }
2212
- // ── Mutations ───────────────────────────────────
2213
- if (operation === "create_definition") {
2214
- return await createDefinition();
2215
- }
2216
- if (operation === "create_goal") {
2217
- const deferredGoalDraft = reuseDeferredDraft && deferredDraft?.operation === "create_goal"
2218
- ? deferredDraft
2219
- : null;
2220
- const editingDeferredGoalDraft = deferredDraftReuseMode === "edit" &&
2221
- deferredGoalDraft?.operation === "create_goal";
2222
- const explicitDescription = detailString(details, "description");
2223
- const explicitCadence = normalizeCadenceDetail(detailObject(details, "cadence"));
2224
- const explicitSuccessCriteria = detailObject(details, "successCriteria");
2225
- const explicitSupportStrategy = detailObject(details, "supportStrategy");
2226
- const explicitMetadata = detailObject(details, "metadata");
2227
- let title = editingDeferredGoalDraft
2228
- ? (params.title ?? deferredGoalDraft?.request.title ?? null)
2229
- : (deferredGoalDraft?.request.title ?? params.title ?? null);
2230
- let description = editingDeferredGoalDraft
2231
- ? (explicitDescription ?? deferredGoalDraft?.request.description)
2232
- : (deferredGoalDraft?.request.description ?? explicitDescription);
2233
- let cadence = editingDeferredGoalDraft
2234
- ? (explicitCadence ?? deferredGoalDraft?.request.cadence)
2235
- : (deferredGoalDraft?.request.cadence ?? explicitCadence);
2236
- let successCriteria = editingDeferredGoalDraft
2237
- ? (explicitSuccessCriteria ??
2238
- deferredGoalDraft?.request.successCriteria)
2239
- : (deferredGoalDraft?.request.successCriteria ??
2240
- explicitSuccessCriteria);
2241
- let supportStrategy = editingDeferredGoalDraft
2242
- ? (explicitSupportStrategy ??
2243
- deferredGoalDraft?.request.supportStrategy)
2244
- : (deferredGoalDraft?.request.supportStrategy ??
2245
- explicitSupportStrategy);
2246
- let goalMetadata = editingDeferredGoalDraft
2247
- ? (explicitMetadata ?? deferredGoalDraft?.request.metadata)
2248
- : (deferredGoalDraft?.request.metadata ?? explicitMetadata);
2249
- let evaluationSummary = null;
2250
- const hasExplicitGroundedGoal = Boolean(title) &&
2251
- (createConfirmed ||
2252
- (Boolean(successCriteria) && Boolean(supportStrategy)));
2253
- if ((!deferredGoalDraft || editingDeferredGoalDraft) &&
2254
- !hasExplicitGroundedGoal) {
2255
- const llmPlan = await extractGoalCreatePlanWithLlm({
2256
- runtime,
2257
- intent,
2258
- state: state ?? undefined,
2259
- message: message ?? undefined,
2260
- });
2261
- if (!title && llmPlan.title) {
2262
- title = llmPlan.title;
2263
- }
2264
- if (!description && llmPlan.description) {
2265
- description = llmPlan.description;
2266
- }
2267
- if (!cadence && llmPlan.cadence) {
2268
- cadence = llmPlan.cadence;
2269
- }
2270
- if (!successCriteria && llmPlan.successCriteria) {
2271
- successCriteria = llmPlan.successCriteria;
2272
- }
2273
- if (!supportStrategy && llmPlan.supportStrategy) {
2274
- supportStrategy = llmPlan.supportStrategy;
2275
- }
2276
- evaluationSummary = llmPlan.evaluationSummary;
2277
- if (llmPlan.groundingState === "grounded" &&
2278
- llmPlan.successCriteria &&
2279
- title) {
2280
- goalMetadata = mergeGoalMetadataWithGrounding({
2281
- metadata: {
2282
- ...(goalMetadata ?? {}),
2283
- source: "chat",
2284
- originalIntent: intent,
2285
- },
2286
- nowIso: new Date().toISOString(),
2287
- plan: llmPlan,
2288
- });
2289
- }
2290
- if (llmPlan.groundingState !== "grounded" ||
2291
- !title ||
2292
- !successCriteria ||
2293
- !supportStrategy) {
2294
- // A clarification request is a successful outcome from the
2295
- // agent's point of view — the agent chose to ask instead of
2296
- // invent an ungrounded goal. Callers rely on `success: true +
2297
- // data.noop: true` to distinguish a deliberate clarify from a
2298
- // handler error.
2299
- return {
2300
- success: true,
2301
- text: llmPlan.response ??
2302
- "What would count as success for that goal, and over what time window?",
2303
- values: {
2304
- success: true,
2305
- error: "NOOP_GOAL_UNGROUNDED",
2306
- noop: true,
2307
- suggestedOperation: "create_goal",
2308
- },
2309
- data: {
2310
- actionName: "LIFE",
2311
- noop: true,
2312
- error: "NOOP_GOAL_UNGROUNDED",
2313
- suggestedOperation: "create_goal",
2314
- },
2315
- };
2316
- }
2317
- }
2318
- if (!title)
2319
- return {
2320
- success: false,
2321
- text: await renderLifeActionReply({
2322
- runtime,
2323
- message,
2324
- state,
2325
- intent,
2326
- scenario: "clarify_create_goal",
2327
- fallback: "What are you trying to achieve?",
2328
- context: {
2329
- missing: ["title"],
2330
- operation: "create_goal",
2331
- },
2332
- }),
2333
- };
2334
- const goalDraft = deferredGoalDraft ?? {
2335
- intent,
2336
- operation: "create_goal",
2337
- createdAt: Date.now(),
2338
- request: {
2339
- cadence,
2340
- description,
2341
- metadata: goalMetadata,
2342
- successCriteria,
2343
- supportStrategy,
2344
- title,
2345
- },
2346
- };
2347
- const experienceLoop = await service.buildGoalExperienceLoop({
2348
- title: goalDraft.request.title,
2349
- description: goalDraft.request.description,
2350
- successCriteria: goalDraft.request.successCriteria ??
2351
- null,
2352
- });
2353
- if (shouldRequireLifeCreateConfirmation({
2354
- confirmed: createConfirmed,
2355
- messageSource: typeof message.content?.source === "string"
2356
- ? message.content.source
2357
- : undefined,
2358
- })) {
2359
- const fallbackParts = [
2360
- evaluationSummary
2361
- ? `I can save "${goalDraft.request.title}" as a goal. Success looks like this: ${evaluationSummary} Confirm and I'll save it, or tell me what to change.`
2362
- : `I can save this goal as "${goalDraft.request.title}". Confirm and I'll save it, or tell me what to change.`,
2363
- ];
2364
- const experienceSummary = formatGoalExperienceLoopSummary(experienceLoop);
2365
- if (experienceSummary) {
2366
- fallbackParts.push(experienceSummary);
2367
- }
2368
- return {
2369
- success: true,
2370
- text: await renderLifeActionReply({
2371
- runtime,
2372
- message,
2373
- state,
2374
- intent,
2375
- scenario: "preview_goal",
2376
- fallback: fallbackParts.join(" "),
2377
- context: {
2378
- draft: goalDraft.request,
2379
- groundingSummary: evaluationSummary,
2380
- experienceLoop,
2381
- },
2382
- }),
2383
- data: {
2384
- actionName: "LIFE",
2385
- deferred: true,
2386
- lifeDraft: goalDraft,
2387
- experienceLoop,
2388
- preview: {
2389
- title: goalDraft.request.title,
2390
- },
2391
- },
2392
- };
2393
- }
2394
- const created = await service.createGoal({
2395
- ownership,
2396
- title: goalDraft.request.title,
2397
- description: goalDraft.request.description,
2398
- cadence: goalDraft.request.cadence,
2399
- supportStrategy: goalDraft.request.supportStrategy,
2400
- successCriteria: goalDraft.request.successCriteria,
2401
- metadata: {
2402
- ...(goalDraft.request.metadata ?? {}),
2403
- source: "chat",
2404
- originalIntent: goalDraft.intent || goalDraft.request.title,
2405
- },
2406
- });
2407
- const createdExperienceLoop = await service.buildGoalExperienceLoop({
2408
- goalId: created.goal.id,
2409
- title: created.goal.title,
2410
- description: created.goal.description,
2411
- successCriteria: created.goal.successCriteria ??
2412
- null,
2413
- });
2414
- const experienceSummary = formatGoalExperienceLoopSummary(createdExperienceLoop);
2415
- const fallback = experienceSummary
2416
- ? `Saved goal "${created.goal.title}". ${experienceSummary}`
2417
- : `Saved goal "${created.goal.title}".`;
2418
- return {
2419
- success: true,
2420
- text: await renderLifeActionReply({
2421
- runtime,
2422
- message,
2423
- state,
2424
- intent,
2425
- scenario: "saved_goal",
2426
- fallback,
2427
- context: {
2428
- created: {
2429
- title: created.goal.title,
2430
- cadence: created.goal.cadence,
2431
- },
2432
- experienceLoop: createdExperienceLoop,
2433
- },
2434
- }),
2435
- data: toActionData({
2436
- ...created,
2437
- experienceLoop: createdExperienceLoop,
2438
- }),
2439
- };
2440
- }
2441
- if (operation === "update_definition") {
2442
- const target = await resolveDefinition(service, targetName, domain);
2443
- if (!target)
2444
- return {
2445
- success: false,
2446
- text: "I could not find that item to update.",
2447
- };
2448
- const request = {
2449
- ownership,
2450
- title: params.title !== target.definition.title ? params.title : undefined,
2451
- description: detailString(details, "description"),
2452
- cadence: normalizeCadenceDetail(detailObject(details, "cadence")),
2453
- priority: detailNumber(details, "priority"),
2454
- windowPolicy: detailObject(details, "windowPolicy"),
2455
- reminderPlan: detailObject(details, "reminderPlan"),
2456
- };
2457
- // If no explicit changes from structured details, try LLM extraction
2458
- const hasExplicitChanges = hasDefinitionUpdateChanges(request);
2459
- if (!hasExplicitChanges && intent) {
2460
- const llmFields = await extractUpdateFieldsWithLlm({
2461
- runtime,
2462
- intent,
2463
- currentTitle: target.definition.title,
2464
- currentCadenceKind: target.definition.cadence.kind,
2465
- currentWindows: target.definition.windowPolicy?.windows?.map((w) => w.name) ?? [],
2466
- });
2467
- if (llmFields) {
2468
- if (llmFields.title)
2469
- request.title = llmFields.title;
2470
- if (llmFields.priority)
2471
- request.priority = llmFields.priority;
2472
- if (llmFields.description)
2473
- request.description = llmFields.description;
2474
- if (llmFields.cadenceKind ||
2475
- llmFields.windows ||
2476
- llmFields.weekdays ||
2477
- llmFields.everyMinutes ||
2478
- llmFields.timeOfDay) {
2479
- const built = buildCadenceFromUpdateFields({
2480
- currentCadence: target.definition.cadence,
2481
- currentWindowPolicy: target.definition.windowPolicy,
2482
- timeZone: target.definition.timezone,
2483
- update: llmFields,
2484
- });
2485
- if (built) {
2486
- request.cadence = built.cadence;
2487
- request.windowPolicy = built.windowPolicy;
2488
- }
2489
- }
2490
- }
2491
- }
2492
- if (!hasDefinitionUpdateChanges(request)) {
2493
- return {
2494
- success: false,
2495
- text: `Tell me what to change about "${target.definition.title}" and I'll update it.`,
2496
- };
2497
- }
2498
- const updated = await service.updateDefinition(target.definition.id, request);
2499
- const fallback = `Updated "${updated.definition.title}".`;
2500
- return {
2501
- success: true,
2502
- text: await renderLifeActionReply({
2503
- runtime,
2504
- message,
2505
- state,
2506
- intent,
2507
- scenario: "updated_definition",
2508
- fallback,
2509
- context: {
2510
- previousTitle: target.definition.title,
2511
- updated: {
2512
- title: updated.definition.title,
2513
- },
2514
- },
2515
- }),
2516
- data: toActionData(updated),
2517
- };
2518
- }
2519
- if (operation === "update_goal") {
2520
- const target = await resolveGoal(service, targetName, domain);
2521
- if (!target)
2522
- return {
2523
- success: false,
2524
- text: "I could not find that goal to update.",
2525
- };
2526
- const request = {
2527
- ownership,
2528
- title: params.title !== target.goal.title ? params.title : undefined,
2529
- description: detailString(details, "description"),
2530
- cadence: normalizeCadenceDetail(detailObject(details, "cadence")),
2531
- supportStrategy: detailObject(details, "supportStrategy"),
2532
- successCriteria: detailObject(details, "successCriteria"),
2533
- };
2534
- const hasExplicitGoalChanges = request.title !== undefined ||
2535
- request.description !== undefined ||
2536
- request.cadence !== undefined ||
2537
- request.supportStrategy !== undefined ||
2538
- request.successCriteria !== undefined;
2539
- if (!hasExplicitGoalChanges) {
2540
- const llmPlan = await extractGoalUpdatePlanWithLlm({
2541
- runtime,
2542
- currentGoal: target.goal,
2543
- intent,
2544
- state: state ?? undefined,
2545
- message: message ?? undefined,
2546
- });
2547
- if (llmPlan.mode === "respond") {
2548
- return {
2549
- success: true,
2550
- text: llmPlan.response ??
2551
- `Tell me what to change about "${target.goal.title}" and I'll update it.`,
2552
- data: {
2553
- actionName: "LIFE",
2554
- noop: true,
2555
- suggestedOperation: "update_goal",
2556
- },
2557
- };
2558
- }
2559
- if (llmPlan.title)
2560
- request.title = llmPlan.title;
2561
- if (llmPlan.description)
2562
- request.description = llmPlan.description;
2563
- if (llmPlan.cadence)
2564
- request.cadence = llmPlan.cadence;
2565
- if (llmPlan.supportStrategy)
2566
- request.supportStrategy = llmPlan.supportStrategy;
2567
- if (llmPlan.successCriteria)
2568
- request.successCriteria = llmPlan.successCriteria;
2569
- if (llmPlan.groundingState) {
2570
- request.metadata = mergeGoalMetadataWithGrounding({
2571
- metadata: target.goal.metadata,
2572
- nowIso: new Date().toISOString(),
2573
- plan: {
2574
- cadence: llmPlan.cadence,
2575
- confidence: llmPlan.confidence,
2576
- evaluationSummary: llmPlan.evaluationSummary,
2577
- groundingState: llmPlan.groundingState,
2578
- missingCriticalFields: llmPlan.missingCriticalFields,
2579
- successCriteria: llmPlan.successCriteria ?? target.goal.successCriteria,
2580
- targetDomain: llmPlan.targetDomain,
2581
- },
2582
- });
2583
- }
2584
- }
2585
- if (request.title === undefined &&
2586
- request.description === undefined &&
2587
- request.cadence === undefined &&
2588
- request.supportStrategy === undefined &&
2589
- request.successCriteria === undefined &&
2590
- request.metadata === undefined) {
2591
- return {
2592
- success: false,
2593
- text: `Tell me what to change about "${target.goal.title}" and I'll update it.`,
2594
- };
2595
- }
2596
- const updated = await service.updateGoal(target.goal.id, request);
2597
- const fallback = `Updated goal "${updated.goal.title}".`;
2598
- return {
2599
- success: true,
2600
- text: await renderLifeActionReply({
2601
- runtime,
2602
- message,
2603
- state,
2604
- intent,
2605
- scenario: "updated_goal",
2606
- fallback,
2607
- context: {
2608
- previousTitle: target.goal.title,
2609
- updated: {
2610
- title: updated.goal.title,
2611
- },
2612
- },
2613
- }),
2614
- data: toActionData(updated),
2615
- };
2616
- }
2617
- if (operation === "delete_definition") {
2618
- const target = await resolveDefinition(service, targetName, domain);
2619
- if (!target)
2620
- return {
2621
- success: false,
2622
- text: "I could not find that item to delete.",
2623
- };
2624
- await service.deleteDefinition(target.definition.id);
2625
- const fallback = `Deleted "${target.definition.title}" and its occurrences.`;
2626
- return {
2627
- success: true,
2628
- text: await renderLifeActionReply({
2629
- runtime,
2630
- message,
2631
- state,
2632
- intent,
2633
- scenario: "deleted_definition",
2634
- fallback,
2635
- context: {
2636
- deleted: {
2637
- title: target.definition.title,
2638
- },
2639
- },
2640
- }),
2641
- };
2642
- }
2643
- if (operation === "delete_goal") {
2644
- const target = await resolveGoal(service, targetName, domain);
2645
- if (!target)
2646
- return {
2647
- success: false,
2648
- text: "I could not find that goal to delete.",
2649
- };
2650
- await service.deleteGoal(target.goal.id);
2651
- const fallback = `Deleted goal "${target.goal.title}".`;
2652
- return {
2653
- success: true,
2654
- text: await renderLifeActionReply({
2655
- runtime,
2656
- message,
2657
- state,
2658
- intent,
2659
- scenario: "deleted_goal",
2660
- fallback,
2661
- context: {
2662
- deleted: {
2663
- title: target.goal.title,
2664
- },
2665
- },
2666
- }),
2667
- };
2668
- }
2669
- if (operation === "complete_occurrence") {
2670
- const { match: target, ambiguousCandidates } = await resolveOccurrenceWithIntentFallback({
2671
- service,
2672
- target: targetName,
2673
- domain,
2674
- intent,
2675
- operation,
2676
- });
2677
- if (!target) {
2678
- if (ambiguousCandidates.length > 0) {
2679
- return {
2680
- success: false,
2681
- text: `Multiple items match — which one?\n${ambiguousCandidates.map((t) => ` - ${t}`).join("\n")}`,
2682
- };
2683
- }
2684
- return {
2685
- success: false,
2686
- text: "I could not find that active item to complete.",
2687
- };
2688
- }
2689
- const completed = await service.completeOccurrence(target.id, {
2690
- note: detailString(details, "note"),
2691
- });
2692
- const fallback = `Marked "${completed.title}" done.`;
2693
- return {
2694
- success: true,
2695
- text: await renderLifeActionReply({
2696
- runtime,
2697
- message,
2698
- state,
2699
- intent,
2700
- scenario: "completed_occurrence",
2701
- fallback,
2702
- context: {
2703
- completed: {
2704
- title: completed.title,
2705
- },
2706
- note: detailString(details, "note"),
2707
- },
2708
- }),
2709
- data: toActionData(completed),
2710
- };
2711
- }
2712
- if (operation === "skip_occurrence") {
2713
- const { match: target, ambiguousCandidates } = await resolveOccurrenceWithIntentFallback({
2714
- service,
2715
- target: targetName,
2716
- domain,
2717
- intent,
2718
- operation,
2719
- });
2720
- if (!target) {
2721
- if (ambiguousCandidates.length > 0) {
2722
- return {
2723
- success: false,
2724
- text: `Multiple items match — which one?\n${ambiguousCandidates.map((t) => ` - ${t}`).join("\n")}`,
2725
- };
2726
- }
2727
- return {
2728
- success: false,
2729
- text: "I could not find that active item to skip.",
2730
- };
2731
- }
2732
- const skipped = await service.skipOccurrence(target.id);
2733
- const fallback = `Skipped "${skipped.title}".`;
2734
- return {
2735
- success: true,
2736
- text: await renderLifeActionReply({
2737
- runtime,
2738
- message,
2739
- state,
2740
- intent,
2741
- scenario: "skipped_occurrence",
2742
- fallback,
2743
- context: {
2744
- skipped: {
2745
- title: skipped.title,
2746
- },
2747
- },
2748
- }),
2749
- data: toActionData(skipped),
2750
- };
2751
- }
2752
- if (operation === "snooze_occurrence") {
2753
- const { match: target, ambiguousCandidates } = await resolveOccurrenceWithIntentFallback({
2754
- service,
2755
- target: targetName,
2756
- domain,
2757
- intent,
2758
- operation,
2759
- });
2760
- if (!target) {
2761
- if (ambiguousCandidates.length > 0) {
2762
- return {
2763
- success: false,
2764
- text: `Multiple items match — which one?\n${ambiguousCandidates.map((t) => ` - ${t}`).join("\n")}`,
2765
- };
2766
- }
2767
- return {
2768
- success: false,
2769
- text: "I could not find that active item to snooze.",
2770
- };
2771
- }
2772
- const preset = detailString(details, "preset");
2773
- const minutes = detailNumber(details, "minutes");
2774
- const snoozed = await service.snoozeOccurrence(target.id, {
2775
- preset,
2776
- minutes,
2777
- });
2778
- const fallback = `Snoozed "${snoozed.title}".`;
2779
- return {
2780
- success: true,
2781
- text: await renderLifeActionReply({
2782
- runtime,
2783
- message,
2784
- state,
2785
- intent,
2786
- scenario: "snoozed_occurrence",
2787
- fallback,
2788
- context: {
2789
- snoozed: {
2790
- title: snoozed.title,
2791
- },
2792
- preset: preset ?? null,
2793
- minutes: minutes ?? null,
2794
- },
2795
- }),
2796
- data: toActionData(snoozed),
2797
- };
2798
- }
2799
- if (operation === "review_goal") {
2800
- const target = await resolveGoal(service, targetName, domain);
2801
- if (!target) {
2802
- const weeklyReview = await service.reviewGoalsForWeek();
2803
- if (weeklyReview.summary.totalGoals === 0) {
2804
- return {
2805
- success: false,
2806
- text: "I could not find any active goals to review.",
2807
- };
2808
- }
2809
- const fallback = formatWeeklyGoalReview(weeklyReview);
2810
- return {
2811
- success: true,
2812
- text: await renderLifeActionReply({
2813
- runtime,
2814
- message,
2815
- state,
2816
- intent,
2817
- scenario: "weekly_goal_review",
2818
- fallback,
2819
- context: {
2820
- summary: weeklyReview.summary,
2821
- atRiskTitles: weeklyReview.atRisk
2822
- .slice(0, 3)
2823
- .map((review) => review.goal.title),
2824
- needsAttentionTitles: weeklyReview.needsAttention
2825
- .slice(0, 3)
2826
- .map((review) => review.goal.title),
2827
- onTrackTitles: weeklyReview.onTrack
2828
- .slice(0, 3)
2829
- .map((review) => review.goal.title),
2830
- },
2831
- }),
2832
- data: toActionData(weeklyReview),
2833
- };
2834
- }
2835
- const review = await service.reviewGoal(target.goal.id);
2836
- return {
2837
- success: true,
2838
- text: review.summary.explanation,
2839
- data: toActionData(review),
2840
- };
2841
- }
2842
- if (operation === "set_reminder_preference") {
2843
- const reminderIntensityPlan = await extractReminderIntensityWithLlm({
2844
- runtime,
2845
- intent,
2846
- });
2847
- if (reminderIntensityPlan.intensity === "unknown") {
2848
- return {
2849
- success: false,
2850
- text: "I need to know whether you want reminders minimal, normal, persistent, or high priority only.",
2851
- };
2852
- }
2853
- const intensity = reminderIntensityPlan.intensity;
2854
- const target = await resolveDefinitionFromIntent(service, targetName, intent, domain);
2855
- const request = {
2856
- intensity,
2857
- definitionId: target?.definition.id ?? null,
2858
- note: chatText || intent,
2859
- };
2860
- const preference = await service.setReminderPreference(request);
2861
- if (target) {
2862
- const fallback = intensity === "high_priority_only"
2863
- ? `Reminder intensity for "${target.definition.title}" is now high priority only.`
2864
- : `Reminder intensity for "${target.definition.title}" is now ${describeReminderIntensity(preference.effective.intensity)}.`;
2865
- return {
2866
- success: true,
2867
- text: await renderLifeActionReply({
2868
- runtime,
2869
- message,
2870
- state,
2871
- intent,
2872
- scenario: "set_reminder_preference",
2873
- fallback,
2874
- context: {
2875
- scope: "definition",
2876
- targetTitle: target.definition.title,
2877
- intensity: preference.effective.intensity,
2878
- },
2879
- }),
2880
- data: toActionData(preference),
2881
- };
2882
- }
2883
- const fallback = intensity === "high_priority_only"
2884
- ? "Global LifeOps reminders are now high priority only."
2885
- : `Global LifeOps reminders are now ${describeReminderIntensity(preference.effective.intensity)}.`;
2886
- return {
2887
- success: true,
2888
- text: await renderLifeActionReply({
2889
- runtime,
2890
- message,
2891
- state,
2892
- intent,
2893
- scenario: "set_reminder_preference",
2894
- fallback,
2895
- context: {
2896
- scope: "global",
2897
- intensity: preference.effective.intensity,
2898
- },
2899
- }),
2900
- data: toActionData(preference),
2901
- };
2902
- }
2903
- if (operation === "capture_phone") {
2904
- const phoneNumber = detailString(details, "phoneNumber") ?? params.title;
2905
- if (!phoneNumber)
2906
- return {
2907
- success: false,
2908
- text: "I need a phone number to set up SMS or voice contact.",
2909
- };
2910
- const allowSms = detailBoolean(details, "allowSms") ?? true;
2911
- const allowVoice = detailBoolean(details, "allowVoice") ?? false;
2912
- const result = await service.capturePhoneConsent({
2913
- phoneNumber,
2914
- consentGiven: true,
2915
- allowSms,
2916
- allowVoice,
2917
- privacyClass: "private",
2918
- });
2919
- const channels = [];
2920
- if (allowSms)
2921
- channels.push("SMS");
2922
- if (allowVoice)
2923
- channels.push("voice calls");
2924
- const fallback = `Phone number ${result.phoneNumber} saved. Enabled for: ${channels.join(" and ") || "reminders"}.`;
2925
- return {
2926
- success: true,
2927
- text: await renderLifeActionReply({
2928
- runtime,
2929
- message,
2930
- state,
2931
- intent,
2932
- scenario: "captured_phone",
2933
- fallback,
2934
- context: {
2935
- phoneNumber: result.phoneNumber,
2936
- channels,
2937
- },
2938
- }),
2939
- data: toActionData(result),
2940
- };
2941
- }
2942
- if (operation === "configure_escalation") {
2943
- const target = await resolveDefinition(service, targetName, domain);
2944
- if (!target)
2945
- return {
2946
- success: false,
2947
- text: "I could not find that item to configure its reminders.",
2948
- };
2949
- const rawSteps = detailArray(details, "steps") ??
2950
- detailArray(details, "escalationSteps");
2951
- const steps = rawSteps
2952
- ? rawSteps
2953
- .filter((s) => typeof s === "object" && s !== null)
2954
- .map((s) => ({
2955
- channel: String(s.channel ?? "in_app"),
2956
- offsetMinutes: typeof s.offsetMinutes === "number" ? s.offsetMinutes : 0,
2957
- label: typeof s.label === "string"
2958
- ? s.label
2959
- : String(s.channel ?? "reminder"),
2960
- }))
2961
- : [{ channel: "in_app", offsetMinutes: 0, label: "In-app reminder" }];
2962
- const updated = await service.updateDefinition(target.definition.id, {
2963
- ownership,
2964
- reminderPlan: { steps },
2965
- });
2966
- const summary = steps
2967
- .map((s) => `${s.channel} at +${s.offsetMinutes}m`)
2968
- .join(", ");
2969
- const fallback = `Updated reminder plan for "${updated.definition.title}": ${summary}.`;
2970
- return {
2971
- success: true,
2972
- text: await renderLifeActionReply({
2973
- runtime,
2974
- message,
2975
- state,
2976
- intent,
2977
- scenario: "configured_escalation",
2978
- fallback,
2979
- context: {
2980
- targetTitle: updated.definition.title,
2981
- steps,
2982
- },
2983
- }),
2984
- data: toActionData(updated),
2985
- };
2986
- }
2987
- return {
2988
- success: false,
2989
- text: "I didn't understand that life management request.",
2990
- };
2991
- }
2992
- catch (err) {
2993
- if (err instanceof LifeOpsServiceError) {
2994
- const fallback = buildLifeServiceErrorFallback(err, intent);
2995
- return {
2996
- success: false,
2997
- text: await renderLifeActionReply({
2998
- runtime,
2999
- message,
3000
- state,
3001
- intent,
3002
- scenario: "service_error",
3003
- fallback,
3004
- context: {
3005
- status: err.status,
3006
- operation,
3007
- },
3008
- }),
3009
- };
3010
- }
3011
- throw err;
3012
- }
3013
- },
3014
- parameters: [
3015
- {
3016
- name: "action",
3017
- description: "What kind of life operation to perform.",
3018
- required: false,
3019
- schema: {
3020
- type: "string",
3021
- enum: [
3022
- "create",
3023
- "create_goal",
3024
- "update",
3025
- "update_goal",
3026
- "delete",
3027
- "delete_goal",
3028
- "complete",
3029
- "skip",
3030
- "snooze",
3031
- "review",
3032
- "phone",
3033
- "escalation",
3034
- "reminder_preference",
3035
- "calendar",
3036
- "next_event",
3037
- "email",
3038
- "overview",
3039
- ],
3040
- },
3041
- },
3042
- {
3043
- name: "intent",
3044
- description: 'Natural language description of what to do. Examples: "create a daily brushing habit for morning and night", "snooze brushing for 30 minutes", "what\'s on my calendar today".',
3045
- required: false,
3046
- schema: { type: "string" },
3047
- },
3048
- {
3049
- name: "title",
3050
- description: "Name for a new item, or the name of an existing item to act on.",
3051
- required: false,
3052
- schema: { type: "string" },
3053
- },
3054
- {
3055
- name: "target",
3056
- description: "Name or ID of an existing item when different from title (e.g., when renaming).",
3057
- required: false,
3058
- schema: { type: "string" },
3059
- },
3060
- {
3061
- name: "details",
3062
- description: "Structured data when needed. May include: cadence (schedule object), kind (task/habit/routine), description, priority, progressionRule, reminderPlan, confirmed (boolean when the user explicitly approves a previewed create), preset (snooze preset like 15m/30m/1h/tonight/tomorrow_morning), minutes (snooze minutes), phoneNumber, allowSms, allowVoice, steps (escalation steps array), goalId, goalTitle, supportStrategy, successCriteria, note, limit, domain (user_lifeops/agent_ops), or reminder preference targeting.",
3063
- required: false,
3064
- schema: { type: "object" },
3065
- },
3066
- ],
3067
- examples: [
3068
- [
3069
- {
3070
- name: "{{name1}}",
3071
- content: {
3072
- text: "add a todo: pick up dry cleaning tomorrow",
3073
- },
3074
- },
3075
- {
3076
- name: "{{agentName}}",
3077
- content: {
3078
- text: 'I can save "Pick up dry cleaning" for tomorrow. Confirm and I\'ll save it.',
3079
- actions: ["LIFE"],
3080
- },
3081
- },
3082
- ],
3083
- [
3084
- {
3085
- name: "{{name1}}",
3086
- content: {
3087
- text: "what's on my todo list today?",
3088
- },
3089
- },
3090
- {
3091
- name: "{{agentName}}",
3092
- content: {
3093
- text: "You have 2 LifeOps items due today: pick up dry cleaning and call mom.",
3094
- actions: ["LIFE"],
3095
- },
3096
- },
3097
- ],
3098
- [
3099
- {
3100
- name: "{{name1}}",
3101
- content: {
3102
- text: "set a goal to save $5,000 by the end of the year",
3103
- },
3104
- },
3105
- {
3106
- name: "{{agentName}}",
3107
- content: {
3108
- text: 'I can save this goal as "Save $5,000 by the end of the year". Confirm and I\'ll save it, or tell me what to change.',
3109
- actions: ["LIFE"],
3110
- },
3111
- },
3112
- ],
3113
- [
3114
- {
3115
- name: "{{name1}}",
3116
- content: {
3117
- text: "help me remember to drink water",
3118
- },
3119
- },
3120
- {
3121
- name: "{{agentName}}",
3122
- content: {
3123
- text: 'I can set up a "Drink water" habit with a reasonable daytime default cadence. Confirm and I\'ll save it.',
3124
- actions: ["LIFE"],
3125
- },
3126
- },
3127
- ],
3128
- [
3129
- {
3130
- name: "{{name1}}",
3131
- content: {
3132
- text: "help me remember to stretch during the day",
3133
- },
3134
- },
3135
- {
3136
- name: "{{agentName}}",
3137
- content: {
3138
- text: 'I can set up a "Stretch" habit with daytime stretch-break defaults. Confirm and I\'ll save it.',
3139
- actions: ["LIFE"],
3140
- },
3141
- },
3142
- ],
3143
- [
3144
- {
3145
- name: "{{name1}}",
3146
- content: {
3147
- text: "please remind me about my Invisalign on weekdays after lunch",
3148
- },
3149
- },
3150
- {
3151
- name: "{{agentName}}",
3152
- content: {
3153
- text: "I can set up a weekday-after-lunch Invisalign habit. Confirm and I'll save it.",
3154
- actions: ["LIFE"],
3155
- },
3156
- },
3157
- ],
3158
- [
3159
- {
3160
- name: "{{name1}}",
3161
- content: {
3162
- text: "recuérdame cepillarme los dientes por la mañana y por la noche",
3163
- },
3164
- },
3165
- {
3166
- name: "{{agentName}}",
3167
- content: {
3168
- text: 'Puedo guardar el hábito "Brush teeth" para la mañana y la noche. Confirma y lo guardo.',
3169
- actions: ["LIFE"],
3170
- },
3171
- },
3172
- ],
3173
- [
3174
- {
3175
- name: "{{name1}}",
3176
- content: {
3177
- text: "help me brush my teeth at 8 am and 9 pm every day",
3178
- },
3179
- },
3180
- {
3181
- name: "{{agentName}}",
3182
- content: {
3183
- text: 'I can set up a habit named "Brush teeth" for 8 am and 9 pm daily. Confirm and I\'ll save it.',
3184
- actions: ["LIFE"],
3185
- },
3186
- },
3187
- ],
3188
- [
3189
- {
3190
- name: "{{name1}}",
3191
- content: {
3192
- text: "Please remind me to shave twice a week.",
3193
- },
3194
- },
3195
- {
3196
- name: "{{agentName}}",
3197
- content: {
3198
- text: 'I can set up a "Shave" habit with a twice-weekly default cadence. Confirm and I\'ll save it.',
3199
- actions: ["LIFE"],
3200
- },
3201
- },
3202
- ],
3203
- [
3204
- {
3205
- name: "{{name1}}",
3206
- content: {
3207
- text: "what life ops tasks are still left for today?",
3208
- },
3209
- },
3210
- {
3211
- name: "{{agentName}}",
3212
- content: {
3213
- text: "You have 2 LifeOps tasks left for today: call mom and pay rent.",
3214
- actions: ["LIFE"],
3215
- },
3216
- },
3217
- {
3218
- name: "{{name1}}",
3219
- content: {
3220
- text: "anything else in my life ops list i need to get done today?",
3221
- },
3222
- },
3223
- {
3224
- name: "{{agentName}}",
3225
- content: {
3226
- text: "You have 1 LifeOps task left for today: pay rent.",
3227
- actions: ["LIFE"],
3228
- },
3229
- },
3230
- ],
3231
- [
3232
- {
3233
- name: "{{name1}}",
3234
- content: {
3235
- text: "remind me less about brush teeth",
3236
- },
3237
- },
3238
- {
3239
- name: "{{agentName}}",
3240
- content: {
3241
- text: 'Reminder intensity for "Brush teeth" is now minimal.',
3242
- actions: ["LIFE"],
3243
- },
3244
- },
3245
- ],
3246
- ],
3247
- };