@agent-native/core 0.91.0 → 0.91.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/blueprints/action/crud.md +1 -1
  2. package/blueprints/channel/discord.md +1 -1
  3. package/blueprints/provider/stripe.md +1 -1
  4. package/blueprints/sandbox/docker.md +1 -1
  5. package/corpus/README.md +1 -1
  6. package/corpus/core/CHANGELOG.md +26 -0
  7. package/corpus/core/blueprints/action/crud.md +1 -1
  8. package/corpus/core/blueprints/channel/discord.md +1 -1
  9. package/corpus/core/blueprints/provider/stripe.md +1 -1
  10. package/corpus/core/blueprints/sandbox/docker.md +1 -1
  11. package/corpus/core/package.json +6 -5
  12. package/corpus/core/src/agent/run-manager.ts +23 -2
  13. package/corpus/core/src/agent/run-store.ts +2 -2
  14. package/corpus/core/src/cli/add.ts +1 -1
  15. package/corpus/core/src/cli/create.ts +8 -3
  16. package/corpus/core/src/cli/design-connect.ts +53 -9
  17. package/corpus/core/src/cli/index.ts +5 -4
  18. package/corpus/core/src/client/extensions/ExtensionSlot.tsx +7 -0
  19. package/corpus/core/src/client/session-replay.ts +97 -3
  20. package/corpus/core/src/jobs/scheduler.ts +30 -1
  21. package/corpus/core/src/localization/default-messages.ts +21 -0
  22. package/corpus/core/src/templates/default/app/i18n/ar-SA.ts +21 -0
  23. package/corpus/core/src/templates/default/app/i18n/de-DE.ts +21 -0
  24. package/corpus/core/src/templates/default/app/i18n/en-US.ts +21 -0
  25. package/corpus/core/src/templates/default/app/i18n/es-ES.ts +21 -0
  26. package/corpus/core/src/templates/default/app/i18n/fr-FR.ts +21 -0
  27. package/corpus/core/src/templates/default/app/i18n/hi-IN.ts +20 -0
  28. package/corpus/core/src/templates/default/app/i18n/ja-JP.ts +21 -0
  29. package/corpus/core/src/templates/default/app/i18n/ko-KR.ts +20 -0
  30. package/corpus/core/src/templates/default/app/i18n/pt-BR.ts +21 -0
  31. package/corpus/core/src/templates/default/app/i18n/zh-CN.ts +20 -0
  32. package/corpus/core/src/templates/default/app/i18n/zh-TW.ts +19 -0
  33. package/corpus/core/src/templates/default/package.json +2 -2
  34. package/corpus/core/src/templates/headless/package.json +3 -3
  35. package/corpus/core/src/templates/workspace-core/package.json +6 -6
  36. package/corpus/core/src/templates/workspace-root/package.json +2 -2
  37. package/corpus/core/src/triggers/dispatcher.ts +30 -2
  38. package/corpus/core/src/vite/client.ts +96 -1
  39. package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +21 -2
  40. package/corpus/templates/analytics/app/global.css +26 -10
  41. package/corpus/templates/analytics/app/i18n/zh-TW.ts +2 -0
  42. package/corpus/templates/analytics/app/i18n-data.ts +25 -0
  43. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +548 -237
  44. package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +285 -294
  45. package/corpus/templates/analytics/changelog/2026-07-08-console-details-expand-inline-under-each-row-and-the-event-t.md +6 -0
  46. package/corpus/templates/analytics/changelog/2026-07-08-session-replay-clamps-ultra-wide-viewports-while-keeping-the.md +6 -0
  47. package/corpus/templates/analytics/changelog/2026-07-08-session-replay-keeps-a-usable-stage-when-dev-tools-is-open-a.md +6 -0
  48. package/corpus/templates/analytics/changelog/2026-07-08-session-replay-resumes-after-scrubbing-and-expands-console-r.md +6 -0
  49. package/corpus/templates/analytics/changelog/2026-07-08-session-replays-wait-for-full-load-keep-a-normal-viewport-an.md +6 -0
  50. package/corpus/templates/analytics/package.json +2 -2
  51. package/corpus/templates/assets/package.json +2 -2
  52. package/corpus/templates/brain/package.json +2 -2
  53. package/corpus/templates/calendar/AGENTS.md +10 -0
  54. package/corpus/templates/calendar/actions/create-event.ts +5 -1
  55. package/corpus/templates/calendar/actions/event-action-helpers.ts +41 -0
  56. package/corpus/templates/calendar/actions/get-attendee-timezones.ts +28 -0
  57. package/corpus/templates/calendar/actions/set-attendee-timezone.ts +68 -0
  58. package/corpus/templates/calendar/app/components/calendar/EventAttendeesSection.tsx +150 -11
  59. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +36 -1
  60. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +32 -0
  61. package/corpus/templates/calendar/app/hooks/use-attendee-timezones.ts +24 -0
  62. package/corpus/templates/calendar/app/i18n/zh-TW.ts +2 -0
  63. package/corpus/templates/calendar/app/i18n-data.ts +20 -0
  64. package/corpus/templates/calendar/app/lib/attendee-local-time.ts +122 -0
  65. package/corpus/templates/calendar/changelog/2026-07-08-event-details-now-support-extension-widgets-and-you-can-see-.md +6 -0
  66. package/corpus/templates/calendar/changelog/2026-07-08-when-you-invite-guests-to-a-new-event-you-now-appear-in.md +6 -0
  67. package/corpus/templates/calendar/package.json +2 -2
  68. package/corpus/templates/calendar/server/handlers/events.ts +5 -1
  69. package/corpus/templates/calendar/shared/api.ts +6 -0
  70. package/corpus/templates/chat/package.json +2 -2
  71. package/corpus/templates/clips/.agents/skills/meetings/SKILL.md +6 -2
  72. package/corpus/templates/clips/actions/create-meeting.ts +8 -3
  73. package/corpus/templates/clips/actions/list-meetings.ts +31 -3
  74. package/corpus/templates/clips/changelog/2026-07-08-after-finishing-a-desktop-recording-reopening-clips-restor.md +6 -0
  75. package/corpus/templates/clips/changelog/2026-07-08-clips-now-pops-up-to-take-notes-when-you-join-an-adhoc-zoom-.md +6 -0
  76. package/corpus/templates/clips/changelog/2026-07-08-desktop-clip-recordings-are-louder-after-capture-mic-only.md +6 -0
  77. package/corpus/templates/clips/changelog/2026-07-08-meeting-reminders-now-appear-1-minute-before-start-stay-unti.md +6 -0
  78. package/corpus/templates/clips/changelog/2026-07-08-the-desktop-meetings-panel-has-room-for-its-drop-shadow-and-.md +6 -0
  79. package/corpus/templates/clips/chrome-extension/package.json +2 -2
  80. package/corpus/templates/clips/desktop/package.json +2 -2
  81. package/corpus/templates/clips/desktop/src/app.tsx +91 -34
  82. package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +15 -5
  83. package/corpus/templates/clips/desktop/src/lib/meeting-notification-timing.ts +83 -0
  84. package/corpus/templates/clips/desktop/src/lib/native-recording-warm.ts +21 -0
  85. package/corpus/templates/clips/desktop/src/lib/recorder.ts +98 -20
  86. package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +174 -50
  87. package/corpus/templates/clips/desktop/src/styles.css +128 -53
  88. package/corpus/templates/clips/desktop/src-tauri/src/adhoc_meetings_watcher.rs +364 -0
  89. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +1 -1
  90. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +5 -0
  91. package/corpus/templates/clips/desktop/src-tauri/src/meetings_watcher.rs +91 -11
  92. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +69 -19
  93. package/corpus/templates/clips/desktop/src-tauri/src/native_speech.rs +36 -1
  94. package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +62 -10
  95. package/corpus/templates/clips/desktop/src-tauri/src/silence_detector.rs +1 -24
  96. package/corpus/templates/clips/desktop/src-tauri/src/util.rs +36 -1
  97. package/corpus/templates/clips/package.json +2 -2
  98. package/corpus/templates/content/actions/_content-database-personal-view.ts +80 -0
  99. package/corpus/templates/content/actions/get-content-database-personal-view.ts +27 -0
  100. package/corpus/templates/content/actions/update-content-database-personal-view.ts +31 -0
  101. package/corpus/templates/content/actions/update-content-database-view.ts +3 -0
  102. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +1 -1
  103. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +2584 -546
  104. package/corpus/templates/content/app/components/editor/database/filter-sort.ts +220 -18
  105. package/corpus/templates/content/app/hooks/use-content-database.ts +32 -0
  106. package/corpus/templates/content/app/i18n/zh-TW.ts +16 -0
  107. package/corpus/templates/content/app/i18n-data.ts +154 -0
  108. package/corpus/templates/content/changelog/2026-07-08-database-filters-now-support-notion-style-reset-save-for-eve.md +6 -0
  109. package/corpus/templates/content/changelog/2026-07-08-date-filters-can-now-target-a-between-range.md +6 -0
  110. package/corpus/templates/content/package.json +2 -2
  111. package/corpus/templates/content/parity/matrix.md +1 -1
  112. package/corpus/templates/content/parity/matrix.ts +2 -0
  113. package/corpus/templates/content/shared/api.ts +24 -0
  114. package/corpus/templates/design/AGENTS.md +9 -0
  115. package/corpus/templates/design/actions/request-localhost-write-consent.ts +141 -0
  116. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +13 -19
  117. package/corpus/templates/design/package.json +2 -2
  118. package/corpus/templates/design/server/lib/verify-write-grant.ts +4 -2
  119. package/corpus/templates/dispatch/app/i18n/zh-TW.ts +34 -1
  120. package/corpus/templates/dispatch/app/i18n-data.ts +387 -10
  121. package/corpus/templates/dispatch/app/routes/automations.tsx +1 -0
  122. package/corpus/templates/dispatch/changelog/2026-07-08-added-an-automations-page-to-review-pause-and-create.md +6 -0
  123. package/corpus/templates/dispatch/changelog/2026-07-08-destinations-now-shows-outbound-delivery-queue-health.md +6 -0
  124. package/corpus/templates/dispatch/package.json +2 -2
  125. package/corpus/templates/forms/package.json +2 -2
  126. package/corpus/templates/macros/package.json +2 -2
  127. package/corpus/templates/mail/app/hooks/use-emails.ts +56 -44
  128. package/corpus/templates/mail/app/lib/gmail-mutation-queue.ts +325 -0
  129. package/corpus/templates/mail/changelog/2026-07-08-rapid-archive-and-mark-read-now-batch-gmail-updates-so-the-i.md +6 -0
  130. package/corpus/templates/mail/package.json +2 -2
  131. package/corpus/templates/plan/package.json +2 -2
  132. package/corpus/templates/slides/app/components/editor/ImageDropPromptPopover.tsx +46 -29
  133. package/corpus/templates/slides/app/context/DeckContext.tsx +45 -18
  134. package/corpus/templates/slides/app/i18n/ar-SA.ts +4 -0
  135. package/corpus/templates/slides/app/i18n/de-DE.ts +4 -0
  136. package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
  137. package/corpus/templates/slides/app/i18n/es-ES.ts +4 -0
  138. package/corpus/templates/slides/app/i18n/fr-FR.ts +4 -0
  139. package/corpus/templates/slides/app/i18n/hi-IN.ts +4 -0
  140. package/corpus/templates/slides/app/i18n/ja-JP.ts +4 -0
  141. package/corpus/templates/slides/app/i18n/ko-KR.ts +4 -0
  142. package/corpus/templates/slides/app/i18n/pt-BR.ts +4 -0
  143. package/corpus/templates/slides/app/i18n/zh-CN.ts +4 -0
  144. package/corpus/templates/slides/app/i18n/zh-TW.ts +4 -0
  145. package/corpus/templates/slides/app/lib/image-drop-to-agent.ts +115 -0
  146. package/corpus/templates/slides/app/pages/DeckEditor.tsx +22 -13
  147. package/corpus/templates/slides/changelog/2026-07-08-dropping-an-image-onto-a-slide-and-sending-it-to-the-agent-w.md +6 -0
  148. package/corpus/templates/slides/changelog/2026-07-08-undo-works-after-the-agent-edits-a-slide-so-you-can-reverse.md +6 -0
  149. package/corpus/templates/slides/package.json +2 -2
  150. package/dist/agent/run-manager.d.ts.map +1 -1
  151. package/dist/agent/run-manager.js +23 -2
  152. package/dist/agent/run-manager.js.map +1 -1
  153. package/dist/agent/run-store.js +2 -2
  154. package/dist/agent/run-store.js.map +1 -1
  155. package/dist/catalog.json +2 -2
  156. package/dist/cli/add.js +1 -1
  157. package/dist/cli/add.js.map +1 -1
  158. package/dist/cli/create.d.ts.map +1 -1
  159. package/dist/cli/create.js +8 -3
  160. package/dist/cli/create.js.map +1 -1
  161. package/dist/cli/design-connect.d.ts.map +1 -1
  162. package/dist/cli/design-connect.js +40 -10
  163. package/dist/cli/design-connect.js.map +1 -1
  164. package/dist/cli/index.js +5 -4
  165. package/dist/cli/index.js.map +1 -1
  166. package/dist/client/extensions/ExtensionSlot.js +6 -0
  167. package/dist/client/extensions/ExtensionSlot.js.map +1 -1
  168. package/dist/client/session-replay.d.ts +8 -0
  169. package/dist/client/session-replay.d.ts.map +1 -1
  170. package/dist/client/session-replay.js +80 -3
  171. package/dist/client/session-replay.js.map +1 -1
  172. package/dist/collab/routes.d.ts +1 -1
  173. package/dist/jobs/scheduler.js +26 -1
  174. package/dist/jobs/scheduler.js.map +1 -1
  175. package/dist/localization/default-messages.d.ts +19 -0
  176. package/dist/localization/default-messages.d.ts.map +1 -1
  177. package/dist/localization/default-messages.js +19 -0
  178. package/dist/localization/default-messages.js.map +1 -1
  179. package/dist/notifications/routes.d.ts +1 -1
  180. package/dist/observability/routes.d.ts +1 -1
  181. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  182. package/dist/resources/handlers.d.ts +1 -1
  183. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  184. package/dist/templates/default/app/i18n/ar-SA.ts +21 -0
  185. package/dist/templates/default/app/i18n/de-DE.ts +21 -0
  186. package/dist/templates/default/app/i18n/en-US.ts +21 -0
  187. package/dist/templates/default/app/i18n/es-ES.ts +21 -0
  188. package/dist/templates/default/app/i18n/fr-FR.ts +21 -0
  189. package/dist/templates/default/app/i18n/hi-IN.ts +20 -0
  190. package/dist/templates/default/app/i18n/ja-JP.ts +21 -0
  191. package/dist/templates/default/app/i18n/ko-KR.ts +20 -0
  192. package/dist/templates/default/app/i18n/pt-BR.ts +21 -0
  193. package/dist/templates/default/app/i18n/zh-CN.ts +20 -0
  194. package/dist/templates/default/app/i18n/zh-TW.ts +19 -0
  195. package/dist/templates/default/package.json +2 -2
  196. package/dist/templates/headless/package.json +3 -3
  197. package/dist/templates/workspace-core/package.json +6 -6
  198. package/dist/templates/workspace-root/package.json +2 -2
  199. package/dist/triggers/dispatcher.js +27 -2
  200. package/dist/triggers/dispatcher.js.map +1 -1
  201. package/dist/vite/client.d.ts.map +1 -1
  202. package/dist/vite/client.js +70 -1
  203. package/dist/vite/client.js.map +1 -1
  204. package/package.json +7 -6
  205. package/src/templates/default/app/i18n/ar-SA.ts +21 -0
  206. package/src/templates/default/app/i18n/de-DE.ts +21 -0
  207. package/src/templates/default/app/i18n/en-US.ts +21 -0
  208. package/src/templates/default/app/i18n/es-ES.ts +21 -0
  209. package/src/templates/default/app/i18n/fr-FR.ts +21 -0
  210. package/src/templates/default/app/i18n/hi-IN.ts +20 -0
  211. package/src/templates/default/app/i18n/ja-JP.ts +21 -0
  212. package/src/templates/default/app/i18n/ko-KR.ts +20 -0
  213. package/src/templates/default/app/i18n/pt-BR.ts +21 -0
  214. package/src/templates/default/app/i18n/zh-CN.ts +20 -0
  215. package/src/templates/default/app/i18n/zh-TW.ts +19 -0
  216. package/src/templates/default/package.json +2 -2
  217. package/src/templates/headless/package.json +3 -3
  218. package/src/templates/workspace-core/package.json +6 -6
  219. package/src/templates/workspace-root/package.json +2 -2
@@ -0,0 +1,24 @@
1
+ import { useActionMutation, useActionQuery } from "@agent-native/core/client";
2
+ import { useQueryClient } from "@tanstack/react-query";
3
+
4
+ export type AttendeeTimezones = Record<string, string>;
5
+
6
+ export function useAttendeeTimezones() {
7
+ return useActionQuery<AttendeeTimezones>("get-attendee-timezones");
8
+ }
9
+
10
+ export function useSetAttendeeTimezone() {
11
+ const queryClient = useQueryClient();
12
+ return useActionMutation<
13
+ AttendeeTimezones,
14
+ { email: string; timeZone?: string }
15
+ >("set-attendee-timezone", {
16
+ method: "PUT",
17
+ onSuccess: (data) => {
18
+ queryClient.setQueryData(
19
+ ["action", "get-attendee-timezones", undefined],
20
+ data,
21
+ );
22
+ },
23
+ });
24
+ }
@@ -123,6 +123,7 @@ const messages = {
123
123
  },
124
124
  attendees: {
125
125
  addAnotherGuest: "新增另一位來賓",
126
+ clearTimezone: "清除時區",
126
127
  contacts: "聯絡人",
127
128
  contactsReconnect: "需要重新連線聯絡人或目錄存取權限。",
128
129
  directory: "目錄",
@@ -134,6 +135,7 @@ const messages = {
134
135
  otherContacts: "其他聯絡人",
135
136
  removeAttendee: "移除 {{email}}",
136
137
  searchingPeople: "正在搜尋人員",
138
+ setTimezone: "設定時區…",
137
139
  },
138
140
  findTime: {
139
141
  busy: "忙碌",
@@ -134,6 +134,7 @@ const enUS = {
134
134
  },
135
135
  attendees: {
136
136
  addAnotherGuest: "Add another guest",
137
+ clearTimezone: "Clear timezone",
137
138
  contacts: "Contacts",
138
139
  contactsReconnect: "Contacts or directory access needs to be reconnected.",
139
140
  directory: "Directory",
@@ -145,6 +146,7 @@ const enUS = {
145
146
  otherContacts: "Other contacts",
146
147
  removeAttendee: "Remove {{email}}",
147
148
  searchingPeople: "Searching people",
149
+ setTimezone: "Set timezone…",
148
150
  },
149
151
  findTime: {
150
152
  busy: "Busy",
@@ -6123,6 +6125,7 @@ const translatedCalendarRemainingRaw = {
6123
6125
  },
6124
6126
  attendees: {
6125
6127
  addAnotherGuest: "添加另一位来宾",
6128
+ clearTimezone: "清除时区",
6126
6129
  contacts: "联系人",
6127
6130
  contactsReconnect: "需要重新连接联系人或目录访问权限。",
6128
6131
  directory: "目录",
@@ -6134,6 +6137,7 @@ const translatedCalendarRemainingRaw = {
6134
6137
  otherContacts: "其他联系人",
6135
6138
  removeAttendee: "移除 {{email}}",
6136
6139
  searchingPeople: "正在搜索人员",
6140
+ setTimezone: "设置时区…",
6137
6141
  },
6138
6142
  findTime: {
6139
6143
  busy: "忙碌",
@@ -6254,6 +6258,8 @@ const translatedCalendarRemainingRaw = {
6254
6258
  otherContacts: "Otros contactos",
6255
6259
  removeAttendee: "Quitar {{email}}",
6256
6260
  searchingPeople: "Buscando personas",
6261
+ clearTimezone: "Borrar zona horaria",
6262
+ setTimezone: "Establecer zona horaria…",
6257
6263
  },
6258
6264
  findTime: {
6259
6265
  busy: "Ocupado",
@@ -6598,6 +6604,8 @@ const translatedCalendarExactCleanup = {
6598
6604
  otherContacts: "Autres contacts",
6599
6605
  removeAttendee: "Retirer {{email}}",
6600
6606
  searchingPeople: "Recherche de personnes",
6607
+ clearTimezone: "Effacer le fuseau horaire",
6608
+ setTimezone: "Définir le fuseau horaire…",
6601
6609
  },
6602
6610
  findTime: {
6603
6611
  busy: "Occupé",
@@ -6787,6 +6795,8 @@ const translatedCalendarExactCleanup = {
6787
6795
  otherContacts: "Weitere Kontakte",
6788
6796
  removeAttendee: "{{email}} entfernen",
6789
6797
  searchingPeople: "Personen werden gesucht",
6798
+ clearTimezone: "Zeitzone löschen",
6799
+ setTimezone: "Zeitzone festlegen…",
6790
6800
  },
6791
6801
  findTime: {
6792
6802
  busy: "Beschäftigt",
@@ -6966,6 +6976,8 @@ const translatedCalendarExactCleanup = {
6966
6976
  otherContacts: "その他の連絡先",
6967
6977
  removeAttendee: "{{email}} を削除",
6968
6978
  searchingPeople: "ユーザーを検索中",
6979
+ clearTimezone: "タイムゾーンをクリア",
6980
+ setTimezone: "タイムゾーンを設定…",
6969
6981
  },
6970
6982
  findTime: {
6971
6983
  busy: "予定あり",
@@ -7136,6 +7148,8 @@ const translatedCalendarExactCleanup = {
7136
7148
  otherContacts: "기타 연락처",
7137
7149
  removeAttendee: "{{email}} 제거",
7138
7150
  searchingPeople: "사람 검색 중",
7151
+ clearTimezone: "시간대 지우기",
7152
+ setTimezone: "시간대 설정…",
7139
7153
  },
7140
7154
  findTime: {
7141
7155
  busy: "바쁨",
@@ -7315,6 +7329,8 @@ const translatedCalendarExactCleanup = {
7315
7329
  otherContacts: "Outros contatos",
7316
7330
  removeAttendee: "Remover {{email}}",
7317
7331
  searchingPeople: "Pesquisando pessoas",
7332
+ clearTimezone: "Limpar fuso horário",
7333
+ setTimezone: "Definir fuso horário…",
7318
7334
  },
7319
7335
  findTime: {
7320
7336
  busy: "Ocupado",
@@ -7494,6 +7510,8 @@ const translatedCalendarExactCleanup = {
7494
7510
  otherContacts: "अन्य संपर्क",
7495
7511
  removeAttendee: "{{email}} हटाएं",
7496
7512
  searchingPeople: "लोग खोजे जा रहे हैं",
7513
+ clearTimezone: "समय क्षेत्र साफ़ करें",
7514
+ setTimezone: "समय क्षेत्र सेट करें…",
7497
7515
  },
7498
7516
  findTime: {
7499
7517
  busy: "व्यस्त",
@@ -7668,6 +7686,8 @@ const translatedCalendarExactCleanup = {
7668
7686
  otherContacts: "جهات اتصال أخرى",
7669
7687
  removeAttendee: "إزالة {{email}}",
7670
7688
  searchingPeople: "جارٍ البحث عن أشخاص",
7689
+ clearTimezone: "مسح المنطقة الزمنية",
7690
+ setTimezone: "تعيين المنطقة الزمنية…",
7671
7691
  },
7672
7692
  findTime: {
7673
7693
  busy: "مشغول",
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Format and resolve per-attendee local times for an event start.
3
+ *
4
+ * Resolution priority for an attendee's IANA timezone:
5
+ * 1. Self attendee (`attendee.self` or email matches accountEmail) →
6
+ * event.startTimeZone, else the browser timezone
7
+ * 2. Optional `attendee.timeZone` on the attendee object
8
+ * 3. User-stored override from the `attendee-timezones` setting map
9
+ *
10
+ * When no timezone is known, returns null — never invent a zone.
11
+ */
12
+
13
+ export type AttendeeTimezoneSource = {
14
+ email: string;
15
+ self?: boolean;
16
+ timeZone?: string;
17
+ };
18
+
19
+ export type ResolveAttendeeTimezoneInput = {
20
+ attendee: AttendeeTimezoneSource;
21
+ accountEmail?: string;
22
+ eventStartTimeZone?: string;
23
+ /** email (lowercased) → IANA timezone overrides from user settings */
24
+ overrides?: Record<string, string>;
25
+ /** Browser/local fallback for the self attendee when the event has no zone */
26
+ browserTimeZone?: string;
27
+ };
28
+
29
+ export function isSelfAttendee(
30
+ attendee: AttendeeTimezoneSource,
31
+ accountEmail?: string,
32
+ ): boolean {
33
+ if (attendee.self) return true;
34
+ if (!accountEmail) return false;
35
+ return (
36
+ attendee.email.trim().toLowerCase() === accountEmail.trim().toLowerCase()
37
+ );
38
+ }
39
+
40
+ export function isValidIanaTimeZone(
41
+ timeZone: string | undefined | null,
42
+ ): boolean {
43
+ if (!timeZone?.trim()) return false;
44
+ try {
45
+ new Intl.DateTimeFormat("en-US", { timeZone: timeZone.trim() }).format();
46
+ return true;
47
+ } catch {
48
+ return false;
49
+ }
50
+ }
51
+
52
+ export function resolveAttendeeTimeZone(
53
+ input: ResolveAttendeeTimezoneInput,
54
+ ): string | null {
55
+ const {
56
+ attendee,
57
+ accountEmail,
58
+ eventStartTimeZone,
59
+ overrides,
60
+ browserTimeZone,
61
+ } = input;
62
+
63
+ if (isSelfAttendee(attendee, accountEmail)) {
64
+ if (isValidIanaTimeZone(eventStartTimeZone)) {
65
+ return eventStartTimeZone!.trim();
66
+ }
67
+ const browser =
68
+ browserTimeZone?.trim() ||
69
+ (typeof Intl !== "undefined"
70
+ ? Intl.DateTimeFormat().resolvedOptions().timeZone
71
+ : undefined);
72
+ return isValidIanaTimeZone(browser) ? browser!.trim() : null;
73
+ }
74
+
75
+ if (isValidIanaTimeZone(attendee.timeZone)) {
76
+ return attendee.timeZone!.trim();
77
+ }
78
+
79
+ const key = attendee.email.trim().toLowerCase();
80
+ const override = overrides?.[key];
81
+ if (isValidIanaTimeZone(override)) {
82
+ return override!.trim();
83
+ }
84
+
85
+ return null;
86
+ }
87
+
88
+ /**
89
+ * Formats an event start instant in a given IANA timezone as a short local
90
+ * time label, e.g. "6:30 AM EDT".
91
+ */
92
+ export function formatAttendeeLocalTime(
93
+ startIso: string,
94
+ timeZone: string,
95
+ locale = "en-US",
96
+ ): string | null {
97
+ if (!isValidIanaTimeZone(timeZone)) return null;
98
+ const date = new Date(startIso);
99
+ if (Number.isNaN(date.getTime())) return null;
100
+
101
+ try {
102
+ return new Intl.DateTimeFormat(locale, {
103
+ timeZone: timeZone.trim(),
104
+ hour: "numeric",
105
+ minute: "2-digit",
106
+ timeZoneName: "short",
107
+ }).format(date);
108
+ } catch {
109
+ return null;
110
+ }
111
+ }
112
+
113
+ export function getAttendeeLocalTimeLabel(
114
+ input: ResolveAttendeeTimezoneInput & {
115
+ startIso: string;
116
+ locale?: string;
117
+ },
118
+ ): string | null {
119
+ const timeZone = resolveAttendeeTimeZone(input);
120
+ if (!timeZone) return null;
121
+ return formatAttendeeLocalTime(input.startIso, timeZone, input.locale);
122
+ }
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: added
3
+ date: 2026-07-08
4
+ ---
5
+
6
+ Event details now support extension widgets, and you can see each guest's local time next to their email when their timezone is known.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-08
4
+ ---
5
+
6
+ When you invite guests to a new event, you now appear in the Guests list the same way Google Calendar shows you as the organizer.
@@ -69,7 +69,6 @@
69
69
  "@types/node": "^24.2.1",
70
70
  "@types/react": "catalog:",
71
71
  "@types/react-dom": "catalog:",
72
- "@typescript/native-preview": "catalog:",
73
72
  "@vitejs/plugin-react-swc": "^4.0.0",
74
73
  "class-variance-authority": "^0.7.1",
75
74
  "clsx": "^2.1.1",
@@ -94,7 +93,8 @@
94
93
  "tailwind-merge": "^3.5.0",
95
94
  "tailwindcss": "catalog:",
96
95
  "tsx": "^4.20.3",
97
- "typescript": "^6.0.3",
96
+ "typescript": "catalog:",
97
+ "typescript-7": "catalog:",
98
98
  "vaul": "^1.1.2",
99
99
  "vite": "catalog:",
100
100
  "vitest": "catalog:"
@@ -9,6 +9,7 @@ import {
9
9
  type H3Event,
10
10
  } from "h3";
11
11
 
12
+ import { ensureOrganizerInAttendees } from "../../actions/event-action-helpers.js";
12
13
  import type { CalendarEvent } from "../../shared/api.js";
13
14
  import { getGoogleEventColorHex } from "../../shared/google-event-colors.js";
14
15
  import {
@@ -271,6 +272,9 @@ export const createEvent = defineEventHandler(async (event: H3Event) => {
271
272
  id: "",
272
273
  source: "google",
273
274
  accountEmail: acctEmail,
275
+ // Match Google Calendar UI: when inviting guests, include the
276
+ // organizer/self email in attendees so they appear in Guests.
277
+ attendees: ensureOrganizerInAttendees(eventBody.attendees, acctEmail),
274
278
  createdAt: new Date().toISOString(),
275
279
  updatedAt: new Date().toISOString(),
276
280
  };
@@ -302,7 +306,7 @@ export const createEvent = defineEventHandler(async (event: H3Event) => {
302
306
  title: calEvent.title || eventBody.title || "",
303
307
  startTime: calEvent.start,
304
308
  endTime: calEvent.end,
305
- attendees: eventBody.attendees ?? [],
309
+ attendees: calEvent.attendees ?? [],
306
310
  createdBy: email,
307
311
  },
308
312
  { owner: email },
@@ -47,6 +47,12 @@ export interface CalendarEvent {
47
47
  self?: boolean;
48
48
  /** When true, the attendee is optional (Google Calendar `optional`). */
49
49
  optional?: boolean;
50
+ /**
51
+ * Optional IANA timezone for this attendee (e.g. America/New_York).
52
+ * Used to show their local time for the event start when known.
53
+ * Prefer user overrides via `attendee-timezones` settings when absent.
54
+ */
55
+ timeZone?: string;
50
56
  }>;
51
57
  reminders?: Array<{ method: "popup" | "email"; minutes: number }>;
52
58
  /** Whether this event uses the calendar's default reminder policy. */
@@ -60,7 +60,6 @@
60
60
  "@types/node": "^24.2.1",
61
61
  "@types/react": "catalog:",
62
62
  "@types/react-dom": "catalog:",
63
- "@typescript/native-preview": "catalog:",
64
63
  "@xterm/addon-fit": "^0.11.0",
65
64
  "@xterm/addon-web-links": "^0.12.0",
66
65
  "@xterm/xterm": "^6.0.0",
@@ -82,7 +81,8 @@
82
81
  "tailwind-merge": "^3.5.0",
83
82
  "tailwindcss": "catalog:",
84
83
  "tsx": "^4.20.3",
85
- "typescript": "^6.0.3",
84
+ "typescript": "catalog:",
85
+ "typescript-7": "catalog:",
86
86
  "vaul": "^1.1.2",
87
87
  "vite": "catalog:",
88
88
  "vitest": "catalog:"
@@ -58,7 +58,11 @@ Both fields are set by `start-meeting-recording`. Agents that operate on a recor
58
58
 
59
59
  ## Calendar reminders
60
60
 
61
- Calendar events fire a desktop notification **5 minutes before** the meeting start (consumer: the desktop tray in `src-tauri/`). The tray polls `list-meetings`, which reads Google Calendar live, so upcoming reminders do not depend on a manual sync or pre-created `meetings` rows. Agents do not need to schedule reminders manually.
61
+ Calendar events fire a desktop notification **1 minute before** the meeting start and keep it visible until **5 minutes after** start unless dismissed (consumer: the desktop tray in `src-tauri/`). The tray polls `list-meetings`, which reads Google Calendar live, so upcoming reminders do not depend on a manual sync or pre-created `meetings` rows. Agents do not need to schedule reminders manually.
62
+
63
+ ## Adhoc Zoom / Teams detection (desktop)
64
+
65
+ When meetings are enabled, the Clips desktop app also watches for native Zoom (`us.zoom.xos` / `us.zoom.ZoomClips`) and Microsoft Teams (`com.microsoft.teams` / `com.microsoft.teams2`) becoming frontmost. After a short dwell (~9s) it creates an adhoc meeting via `create-meeting` (`source: "adhoc"`) and shows the same Granola-style popup (`type: "adhoc"`, subtitle "Take notes?"). Auto transcription mode also emits `meetings:start-transcription` with reason `adhoc-auto`. Detection skips when a meeting is already being transcribed, when Manual mode has the meeting widget disabled, and soft-skips shortly after a calendar reminder for the same platform.
62
66
 
63
67
  ## Actions
64
68
 
@@ -66,7 +70,7 @@ Calendar events fire a desktop notification **5 minutes before** the meeting sta
66
70
  | ------------------------- | --------------------------------------------------------------------- |
67
71
  | `list-meetings` | Upcoming + past, scoped via `accessFilter`; reads connected Google Calendar live |
68
72
  | `get-meeting` | One meeting + participants + segments + notes |
69
- | `create-meeting` | Internal/escape-hatch meeting row creation; the visible Meetings UI is calendar-sourced |
73
+ | `create-meeting` | Create a meeting row (`source`: `calendar` / `adhoc` / `manual`); desktop adhoc Zoom/Teams detection passes `source: "adhoc"` |
70
74
  | `update-meeting` | Inline title edit, notes edits |
71
75
  | `delete-meeting` | Soft-delete a meeting from the visible list; linked recordings and calendar events stay intact |
72
76
  | `start-meeting-recording` | Begin native macOS transcript stream + create the linked recording |
@@ -65,6 +65,12 @@ export default defineAction({
65
65
  .enum(["private", "org", "public"])
66
66
  .optional()
67
67
  .describe("Initial visibility — defaults to private"),
68
+ source: z
69
+ .enum(["calendar", "adhoc", "manual"])
70
+ .optional()
71
+ .describe(
72
+ "How the meeting was created. Desktop adhoc Zoom/Teams detection passes `adhoc`; omit to infer from title/calendarEventId.",
73
+ ),
68
74
  })
69
75
  .refine((v) => v.title || v.calendarEventId, {
70
76
  message: "Provide either title or calendarEventId",
@@ -86,9 +92,8 @@ export default defineAction({
86
92
  isOrganizer?: boolean;
87
93
  }> = args.participants ?? [];
88
94
  let calendarEventIdLink: string | null = null;
89
- let source: "calendar" | "adhoc" | "manual" = args.title
90
- ? "manual"
91
- : "adhoc";
95
+ let source: "calendar" | "adhoc" | "manual" =
96
+ args.source ?? (args.title ? "manual" : "adhoc");
92
97
 
93
98
  if (args.calendarEventId) {
94
99
  // Verify the user owns the calendar account that hosts this event.
@@ -73,6 +73,15 @@ export default defineAction({
73
73
  .describe(
74
74
  "If set, only return upcoming meetings starting within this many minutes. Used by the desktop reminder watcher.",
75
75
  ),
76
+ includeStartedWithinMin: z.coerce
77
+ .number()
78
+ .int()
79
+ .min(0)
80
+ .max(60)
81
+ .optional()
82
+ .describe(
83
+ "Also include meetings that started within this many minutes (desktop reminder hold window). Default 0.",
84
+ ),
76
85
  }),
77
86
  http: { method: "GET" },
78
87
  run: async (args) => {
@@ -92,6 +101,11 @@ export default defineAction({
92
101
  now.getTime() + args.upcomingWithinMin * 60 * 1000,
93
102
  ).toISOString()
94
103
  : null;
104
+ const startedWithinMin = args.includeStartedWithinMin ?? 0;
105
+ const upcomingWindowMinIso =
106
+ startedWithinMin > 0
107
+ ? new Date(now.getTime() - startedWithinMin * 60 * 1000).toISOString()
108
+ : nowIso;
95
109
 
96
110
  const whereClauses = [accessFilter(schema.meetings, schema.meetingShares)];
97
111
 
@@ -102,11 +116,12 @@ export default defineAction({
102
116
  }
103
117
 
104
118
  if (args.view === "upcoming") {
105
- // Scheduled in the future and not yet finished.
119
+ // Scheduled in the future (or recently started, for desktop hold window)
120
+ // and not yet finished.
106
121
  whereClauses.push(
107
122
  and(
108
123
  isNotNull(schema.meetings.scheduledStart),
109
- gte(schema.meetings.scheduledStart, nowIso),
124
+ gte(schema.meetings.scheduledStart, upcomingWindowMinIso),
110
125
  isNull(schema.meetings.actualStart),
111
126
  isNull(schema.meetings.actualEnd),
112
127
  upcomingWindowMaxIso
@@ -209,7 +224,10 @@ export default defineAction({
209
224
  ? new Date(now.getTime() - THIRTY_DAYS_MS).toISOString()
210
225
  : args.view === "all"
211
226
  ? new Date(now.getTime() - THIRTY_DAYS_MS).toISOString()
212
- : new Date(now.getTime() - 60 * 1000).toISOString();
227
+ : startedWithinMin > 0
228
+ ? upcomingWindowMinIso
229
+ : // Small cushion for clock skew when listing pure upcoming.
230
+ new Date(now.getTime() - 60 * 1000).toISOString();
213
231
  const timeMax =
214
232
  args.view === "past"
215
233
  ? nowIso
@@ -253,6 +271,16 @@ export default defineAction({
253
271
  const endMs = Date.parse(endIso);
254
272
  if (Number.isNaN(startMs) || Number.isNaN(endMs)) continue;
255
273
  if (args.view === "upcoming" && endMs < now.getTime()) continue;
274
+ // Only clamp already-started events when the desktop hold window
275
+ // is active — the normal Meetings list still shows in-progress
276
+ // calendar events until they end.
277
+ if (
278
+ args.view === "upcoming" &&
279
+ startedWithinMin > 0 &&
280
+ startMs < Date.parse(upcomingWindowMinIso)
281
+ ) {
282
+ continue;
283
+ }
256
284
  if (args.view === "past" && endMs >= now.getTime()) continue;
257
285
  if (
258
286
  upcomingWindowMaxIso &&
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-08
4
+ ---
5
+
6
+ After finishing a desktop recording, reopening Clips restores the camera preview and Start Recording works again instead of doing nothing.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: added
3
+ date: 2026-07-08
4
+ ---
5
+
6
+ Clips now pops up to take notes when you join an adhoc Zoom or Teams call, like Granola.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-08
4
+ ---
5
+
6
+ Desktop clip recordings are louder after capture — mic-only clips skip the half-volume downmix and get a stronger pre-gain before loudness normalization; mic+system clips get makeup gain so the centered mix is not systematically quieter.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-08
4
+ ---
5
+
6
+ Meeting reminders now appear 1 minute before start, stay until 5 minutes in, and use a Granola-style Join & open Clips button
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-08
4
+ ---
5
+
6
+ The desktop Meetings panel has room for its drop shadow and a little more space below the last meeting.
@@ -7,7 +7,7 @@
7
7
  "dev": "vite build --watch",
8
8
  "dev:hot": "tsx scripts/dev.ts",
9
9
  "build": "vite build",
10
- "typecheck": "tsgo --noEmit",
10
+ "typecheck": "tsc --noEmit",
11
11
  "package": "pnpm build && tsx scripts/package.ts"
12
12
  },
13
13
  "dependencies": {
@@ -15,9 +15,9 @@
15
15
  },
16
16
  "devDependencies": {
17
17
  "@types/chrome": "^0.2.0",
18
- "@typescript/native-preview": "catalog:",
19
18
  "tsx": "catalog:",
20
19
  "typescript": "catalog:",
20
+ "typescript-7": "catalog:",
21
21
  "vite": "catalog:"
22
22
  }
23
23
  }
@@ -31,9 +31,9 @@
31
31
  "@tauri-apps/cli": "^2.11.2",
32
32
  "@types/react": "^19.2.14",
33
33
  "@types/react-dom": "^19.2.3",
34
- "@typescript/native-preview": "catalog:",
35
34
  "@vitejs/plugin-react": "catalog:",
36
- "typescript": "^6.0.3",
35
+ "typescript": "catalog:",
36
+ "typescript-7": "catalog:",
37
37
  "vite": "catalog:"
38
38
  }
39
39
  }