@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.
- package/blueprints/action/crud.md +1 -1
- package/blueprints/channel/discord.md +1 -1
- package/blueprints/provider/stripe.md +1 -1
- package/blueprints/sandbox/docker.md +1 -1
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +26 -0
- package/corpus/core/blueprints/action/crud.md +1 -1
- package/corpus/core/blueprints/channel/discord.md +1 -1
- package/corpus/core/blueprints/provider/stripe.md +1 -1
- package/corpus/core/blueprints/sandbox/docker.md +1 -1
- package/corpus/core/package.json +6 -5
- package/corpus/core/src/agent/run-manager.ts +23 -2
- package/corpus/core/src/agent/run-store.ts +2 -2
- package/corpus/core/src/cli/add.ts +1 -1
- package/corpus/core/src/cli/create.ts +8 -3
- package/corpus/core/src/cli/design-connect.ts +53 -9
- package/corpus/core/src/cli/index.ts +5 -4
- package/corpus/core/src/client/extensions/ExtensionSlot.tsx +7 -0
- package/corpus/core/src/client/session-replay.ts +97 -3
- package/corpus/core/src/jobs/scheduler.ts +30 -1
- package/corpus/core/src/localization/default-messages.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/ar-SA.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/de-DE.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/en-US.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/es-ES.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/fr-FR.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/hi-IN.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/ja-JP.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/ko-KR.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/pt-BR.ts +21 -0
- package/corpus/core/src/templates/default/app/i18n/zh-CN.ts +20 -0
- package/corpus/core/src/templates/default/app/i18n/zh-TW.ts +19 -0
- package/corpus/core/src/templates/default/package.json +2 -2
- package/corpus/core/src/templates/headless/package.json +3 -3
- package/corpus/core/src/templates/workspace-core/package.json +6 -6
- package/corpus/core/src/templates/workspace-root/package.json +2 -2
- package/corpus/core/src/triggers/dispatcher.ts +30 -2
- package/corpus/core/src/vite/client.ts +96 -1
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +21 -2
- package/corpus/templates/analytics/app/global.css +26 -10
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +2 -0
- package/corpus/templates/analytics/app/i18n-data.ts +25 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +548 -237
- package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +285 -294
- package/corpus/templates/analytics/changelog/2026-07-08-console-details-expand-inline-under-each-row-and-the-event-t.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-session-replay-clamps-ultra-wide-viewports-while-keeping-the.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-session-replay-keeps-a-usable-stage-when-dev-tools-is-open-a.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-session-replay-resumes-after-scrubbing-and-expands-console-r.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-session-replays-wait-for-full-load-keep-a-normal-viewport-an.md +6 -0
- package/corpus/templates/analytics/package.json +2 -2
- package/corpus/templates/assets/package.json +2 -2
- package/corpus/templates/brain/package.json +2 -2
- package/corpus/templates/calendar/AGENTS.md +10 -0
- package/corpus/templates/calendar/actions/create-event.ts +5 -1
- package/corpus/templates/calendar/actions/event-action-helpers.ts +41 -0
- package/corpus/templates/calendar/actions/get-attendee-timezones.ts +28 -0
- package/corpus/templates/calendar/actions/set-attendee-timezone.ts +68 -0
- package/corpus/templates/calendar/app/components/calendar/EventAttendeesSection.tsx +150 -11
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +36 -1
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +32 -0
- package/corpus/templates/calendar/app/hooks/use-attendee-timezones.ts +24 -0
- package/corpus/templates/calendar/app/i18n/zh-TW.ts +2 -0
- package/corpus/templates/calendar/app/i18n-data.ts +20 -0
- package/corpus/templates/calendar/app/lib/attendee-local-time.ts +122 -0
- package/corpus/templates/calendar/changelog/2026-07-08-event-details-now-support-extension-widgets-and-you-can-see-.md +6 -0
- package/corpus/templates/calendar/changelog/2026-07-08-when-you-invite-guests-to-a-new-event-you-now-appear-in.md +6 -0
- package/corpus/templates/calendar/package.json +2 -2
- package/corpus/templates/calendar/server/handlers/events.ts +5 -1
- package/corpus/templates/calendar/shared/api.ts +6 -0
- package/corpus/templates/chat/package.json +2 -2
- package/corpus/templates/clips/.agents/skills/meetings/SKILL.md +6 -2
- package/corpus/templates/clips/actions/create-meeting.ts +8 -3
- package/corpus/templates/clips/actions/list-meetings.ts +31 -3
- package/corpus/templates/clips/changelog/2026-07-08-after-finishing-a-desktop-recording-reopening-clips-restor.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-clips-now-pops-up-to-take-notes-when-you-join-an-adhoc-zoom-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-desktop-clip-recordings-are-louder-after-capture-mic-only.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-meeting-reminders-now-appear-1-minute-before-start-stay-unti.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-the-desktop-meetings-panel-has-room-for-its-drop-shadow-and-.md +6 -0
- package/corpus/templates/clips/chrome-extension/package.json +2 -2
- package/corpus/templates/clips/desktop/package.json +2 -2
- package/corpus/templates/clips/desktop/src/app.tsx +91 -34
- package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +15 -5
- package/corpus/templates/clips/desktop/src/lib/meeting-notification-timing.ts +83 -0
- package/corpus/templates/clips/desktop/src/lib/native-recording-warm.ts +21 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +98 -20
- package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +174 -50
- package/corpus/templates/clips/desktop/src/styles.css +128 -53
- package/corpus/templates/clips/desktop/src-tauri/src/adhoc_meetings_watcher.rs +364 -0
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +1 -1
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +5 -0
- package/corpus/templates/clips/desktop/src-tauri/src/meetings_watcher.rs +91 -11
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +69 -19
- package/corpus/templates/clips/desktop/src-tauri/src/native_speech.rs +36 -1
- package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +62 -10
- package/corpus/templates/clips/desktop/src-tauri/src/silence_detector.rs +1 -24
- package/corpus/templates/clips/desktop/src-tauri/src/util.rs +36 -1
- package/corpus/templates/clips/package.json +2 -2
- package/corpus/templates/content/actions/_content-database-personal-view.ts +80 -0
- package/corpus/templates/content/actions/get-content-database-personal-view.ts +27 -0
- package/corpus/templates/content/actions/update-content-database-personal-view.ts +31 -0
- package/corpus/templates/content/actions/update-content-database-view.ts +3 -0
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +1 -1
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +2584 -546
- package/corpus/templates/content/app/components/editor/database/filter-sort.ts +220 -18
- package/corpus/templates/content/app/hooks/use-content-database.ts +32 -0
- package/corpus/templates/content/app/i18n/zh-TW.ts +16 -0
- package/corpus/templates/content/app/i18n-data.ts +154 -0
- package/corpus/templates/content/changelog/2026-07-08-database-filters-now-support-notion-style-reset-save-for-eve.md +6 -0
- package/corpus/templates/content/changelog/2026-07-08-date-filters-can-now-target-a-between-range.md +6 -0
- package/corpus/templates/content/package.json +2 -2
- package/corpus/templates/content/parity/matrix.md +1 -1
- package/corpus/templates/content/parity/matrix.ts +2 -0
- package/corpus/templates/content/shared/api.ts +24 -0
- package/corpus/templates/design/AGENTS.md +9 -0
- package/corpus/templates/design/actions/request-localhost-write-consent.ts +141 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +13 -19
- package/corpus/templates/design/package.json +2 -2
- package/corpus/templates/design/server/lib/verify-write-grant.ts +4 -2
- package/corpus/templates/dispatch/app/i18n/zh-TW.ts +34 -1
- package/corpus/templates/dispatch/app/i18n-data.ts +387 -10
- package/corpus/templates/dispatch/app/routes/automations.tsx +1 -0
- package/corpus/templates/dispatch/changelog/2026-07-08-added-an-automations-page-to-review-pause-and-create.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-07-08-destinations-now-shows-outbound-delivery-queue-health.md +6 -0
- package/corpus/templates/dispatch/package.json +2 -2
- package/corpus/templates/forms/package.json +2 -2
- package/corpus/templates/macros/package.json +2 -2
- package/corpus/templates/mail/app/hooks/use-emails.ts +56 -44
- package/corpus/templates/mail/app/lib/gmail-mutation-queue.ts +325 -0
- package/corpus/templates/mail/changelog/2026-07-08-rapid-archive-and-mark-read-now-batch-gmail-updates-so-the-i.md +6 -0
- package/corpus/templates/mail/package.json +2 -2
- package/corpus/templates/plan/package.json +2 -2
- package/corpus/templates/slides/app/components/editor/ImageDropPromptPopover.tsx +46 -29
- package/corpus/templates/slides/app/context/DeckContext.tsx +45 -18
- package/corpus/templates/slides/app/i18n/ar-SA.ts +4 -0
- package/corpus/templates/slides/app/i18n/de-DE.ts +4 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
- package/corpus/templates/slides/app/i18n/es-ES.ts +4 -0
- package/corpus/templates/slides/app/i18n/fr-FR.ts +4 -0
- package/corpus/templates/slides/app/i18n/hi-IN.ts +4 -0
- package/corpus/templates/slides/app/i18n/ja-JP.ts +4 -0
- package/corpus/templates/slides/app/i18n/ko-KR.ts +4 -0
- package/corpus/templates/slides/app/i18n/pt-BR.ts +4 -0
- package/corpus/templates/slides/app/i18n/zh-CN.ts +4 -0
- package/corpus/templates/slides/app/i18n/zh-TW.ts +4 -0
- package/corpus/templates/slides/app/lib/image-drop-to-agent.ts +115 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +22 -13
- package/corpus/templates/slides/changelog/2026-07-08-dropping-an-image-onto-a-slide-and-sending-it-to-the-agent-w.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-08-undo-works-after-the-agent-edits-a-slide-so-you-can-reverse.md +6 -0
- package/corpus/templates/slides/package.json +2 -2
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +23 -2
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.js +2 -2
- package/dist/agent/run-store.js.map +1 -1
- package/dist/catalog.json +2 -2
- package/dist/cli/add.js +1 -1
- package/dist/cli/add.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +8 -3
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +40 -10
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/cli/index.js +5 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/client/extensions/ExtensionSlot.js +6 -0
- package/dist/client/extensions/ExtensionSlot.js.map +1 -1
- package/dist/client/session-replay.d.ts +8 -0
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +80 -3
- package/dist/client/session-replay.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/jobs/scheduler.js +26 -1
- package/dist/jobs/scheduler.js.map +1 -1
- package/dist/localization/default-messages.d.ts +19 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +19 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/templates/default/app/i18n/ar-SA.ts +21 -0
- package/dist/templates/default/app/i18n/de-DE.ts +21 -0
- package/dist/templates/default/app/i18n/en-US.ts +21 -0
- package/dist/templates/default/app/i18n/es-ES.ts +21 -0
- package/dist/templates/default/app/i18n/fr-FR.ts +21 -0
- package/dist/templates/default/app/i18n/hi-IN.ts +20 -0
- package/dist/templates/default/app/i18n/ja-JP.ts +21 -0
- package/dist/templates/default/app/i18n/ko-KR.ts +20 -0
- package/dist/templates/default/app/i18n/pt-BR.ts +21 -0
- package/dist/templates/default/app/i18n/zh-CN.ts +20 -0
- package/dist/templates/default/app/i18n/zh-TW.ts +19 -0
- package/dist/templates/default/package.json +2 -2
- package/dist/templates/headless/package.json +3 -3
- package/dist/templates/workspace-core/package.json +6 -6
- package/dist/templates/workspace-root/package.json +2 -2
- package/dist/triggers/dispatcher.js +27 -2
- package/dist/triggers/dispatcher.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +70 -1
- package/dist/vite/client.js.map +1 -1
- package/package.json +7 -6
- package/src/templates/default/app/i18n/ar-SA.ts +21 -0
- package/src/templates/default/app/i18n/de-DE.ts +21 -0
- package/src/templates/default/app/i18n/en-US.ts +21 -0
- package/src/templates/default/app/i18n/es-ES.ts +21 -0
- package/src/templates/default/app/i18n/fr-FR.ts +21 -0
- package/src/templates/default/app/i18n/hi-IN.ts +20 -0
- package/src/templates/default/app/i18n/ja-JP.ts +21 -0
- package/src/templates/default/app/i18n/ko-KR.ts +20 -0
- package/src/templates/default/app/i18n/pt-BR.ts +21 -0
- package/src/templates/default/app/i18n/zh-CN.ts +20 -0
- package/src/templates/default/app/i18n/zh-TW.ts +19 -0
- package/src/templates/default/package.json +2 -2
- package/src/templates/headless/package.json +3 -3
- package/src/templates/workspace-core/package.json +6 -6
- 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
|
+
}
|
|
@@ -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": "
|
|
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:
|
|
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": "
|
|
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 **
|
|
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` |
|
|
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" =
|
|
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
|
|
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,
|
|
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
|
-
:
|
|
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
|
+
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.
|
|
@@ -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": "
|
|
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": "
|
|
35
|
+
"typescript": "catalog:",
|
|
36
|
+
"typescript-7": "catalog:",
|
|
37
37
|
"vite": "catalog:"
|
|
38
38
|
}
|
|
39
39
|
}
|