@agent-native/core 0.90.3 → 0.90.4
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/bin/agent-native.js +25 -3
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +9 -0
- package/corpus/core/bin/agent-native.js +25 -3
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/engine/index.ts +1 -0
- package/corpus/core/src/agent/engine/registry.ts +63 -2
- package/corpus/core/src/cli/create.ts +35 -0
- package/corpus/core/src/cli/design-connect.ts +248 -0
- package/corpus/core/src/cli/index.ts +84 -7
- package/corpus/core/src/cli/workspacify.ts +34 -0
- package/corpus/core/src/client/history/VersionHistoryPanel.tsx +77 -47
- package/corpus/core/src/client/history/index.ts +3 -0
- package/corpus/core/src/client/history/use-history.ts +28 -0
- package/corpus/core/src/client/index.ts +8 -0
- package/corpus/core/src/client/review/index.ts +5 -0
- package/corpus/core/src/client/review/use-review.ts +40 -2
- package/corpus/core/src/history/actions/create-resource-version.ts +11 -8
- package/corpus/core/src/history/index.ts +0 -1
- package/corpus/core/src/history/registry.ts +24 -12
- package/corpus/core/src/history/store.ts +84 -53
- package/corpus/core/src/review/actions/consume-review-feedback.ts +15 -5
- package/corpus/core/src/review/actions/delete-review-comment.ts +15 -3
- package/corpus/core/src/review/actions/resolve-review-thread.ts +12 -5
- package/corpus/core/src/review/index.ts +0 -5
- package/corpus/core/src/review/registry.ts +24 -12
- package/corpus/core/src/review/store.ts +10 -7
- package/corpus/core/src/server/agent-chat-plugin.ts +6 -0
- package/corpus/core/src/server/credential-provider.ts +13 -3
- package/corpus/templates/assets/actions/_preset-skeleton-validation.ts +11 -11
- package/corpus/templates/assets/actions/generate-image.ts +64 -28
- package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +1 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +91 -74
- package/corpus/templates/assets/server/lib/generation.ts +29 -4
- package/corpus/templates/assets/server/lib/image-processing.ts +131 -0
- package/corpus/templates/calendar/.agents/skills/event-management/SKILL.md +24 -2
- package/corpus/templates/calendar/AGENTS.md +3 -0
- package/corpus/templates/calendar/actions/create-event.ts +8 -34
- package/corpus/templates/calendar/actions/event-action-helpers.ts +52 -0
- package/corpus/templates/calendar/actions/manage-event-draft.ts +7 -34
- package/corpus/templates/calendar/actions/update-event.ts +10 -23
- package/corpus/templates/calendar/app/components/calendar/AttendeeAutocomplete.tsx +47 -0
- package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +23 -0
- package/corpus/templates/calendar/app/components/calendar/EventAttendeesSection.tsx +59 -2
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +40 -1
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +34 -1
- package/corpus/templates/calendar/app/hooks/use-events.ts +6 -0
- package/corpus/templates/calendar/app/i18n/zh-TW.ts +4 -0
- package/corpus/templates/calendar/app/i18n-data.ts +40 -0
- package/corpus/templates/calendar/changelog/2026-07-07-you-can-mark-event-guests-as-optional-while-inviting-them-or.md +6 -0
- package/corpus/templates/calendar/server/handlers/events.ts +1 -0
- package/corpus/templates/calendar/server/lib/google-calendar.ts +4 -0
- package/corpus/templates/calendar/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/calendar/shared/api.ts +2 -0
- package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +29 -3
- package/corpus/templates/clips/actions/generate-workflow.ts +19 -8
- package/corpus/templates/clips/actions/get-clips-ai-prefs.ts +36 -0
- package/corpus/templates/clips/actions/lib/clips-ai-prefs.ts +28 -0
- package/corpus/templates/clips/actions/regenerate-chapters.ts +21 -7
- package/corpus/templates/clips/actions/regenerate-summary.ts +26 -8
- package/corpus/templates/clips/actions/regenerate-title.ts +44 -7
- package/corpus/templates/clips/actions/update-clips-ai-prefs.ts +50 -0
- package/corpus/templates/clips/app/components/meetings/meeting-card.tsx +7 -2
- package/corpus/templates/clips/app/hooks/use-auto-title.ts +25 -10
- package/corpus/templates/clips/app/i18n/ar-SA.ts +28 -6
- package/corpus/templates/clips/app/i18n/de-DE.ts +28 -6
- package/corpus/templates/clips/app/i18n/en-US.ts +29 -6
- package/corpus/templates/clips/app/i18n/es-ES.ts +29 -6
- package/corpus/templates/clips/app/i18n/fr-FR.ts +30 -6
- package/corpus/templates/clips/app/i18n/hi-IN.ts +26 -6
- package/corpus/templates/clips/app/i18n/ja-JP.ts +27 -6
- package/corpus/templates/clips/app/i18n/ko-KR.ts +28 -6
- package/corpus/templates/clips/app/i18n/pt-BR.ts +28 -6
- package/corpus/templates/clips/app/i18n/zh-CN.ts +26 -6
- package/corpus/templates/clips/app/i18n/zh-TW.ts +25 -6
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +73 -0
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +1 -0
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +70 -2
- package/corpus/templates/clips/changelog/2026-07-07-ai-tools-can-include-the-full-video-not-just-the-transcript-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-07-clips-desktop-now-surfaces-meetings-and-dictate-directly-in-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-07-meeting-notes-now-explain-exactly-how-to-start-granola-style.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-07-meeting-start-alerts-now-include-separate-start-notes-and-jo.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-07-recordings-start-more-predictably-and-newly-saved-clips-refr.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
- package/corpus/templates/clips/desktop/src/app.tsx +435 -105
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +27 -21
- package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +23 -22
- package/corpus/templates/clips/desktop/src/styles.css +167 -2
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +1 -1
- package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +3 -7
- package/corpus/templates/clips/desktop/src-tauri/src/tray_meetings.rs +5 -4
- package/corpus/templates/clips/server/routes/_agent-native/clips/user-prefs.put.ts +16 -8
- package/corpus/templates/clips/shared/clips-ai-prefs.ts +81 -0
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +16 -1
- package/corpus/templates/design/actions/add-localhost-screens.ts +1 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +345 -11
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +89 -14
- package/corpus/templates/design/app/components/design/bridge-security.ts +7 -1
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +1 -1
- package/corpus/templates/design/app/i18n/zh-TW.ts +3 -0
- package/corpus/templates/design/app/i18n-data.ts +41 -0
- package/corpus/templates/design/changelog/2026-07-07-local-visual-edit-uses-live-app-iframes-for-click-to-edit-pr.md +6 -0
- package/dist/agent/engine/index.d.ts +1 -1
- package/dist/agent/engine/index.d.ts.map +1 -1
- package/dist/agent/engine/index.js +1 -1
- package/dist/agent/engine/index.js.map +1 -1
- package/dist/agent/engine/registry.d.ts +14 -0
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js +56 -2
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +31 -0
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +186 -0
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/cli/index.js +76 -9
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/workspacify.d.ts.map +1 -1
- package/dist/cli/workspacify.js +30 -0
- package/dist/cli/workspacify.js.map +1 -1
- package/dist/client/history/VersionHistoryPanel.d.ts +1 -1
- package/dist/client/history/VersionHistoryPanel.d.ts.map +1 -1
- package/dist/client/history/VersionHistoryPanel.js +12 -5
- package/dist/client/history/VersionHistoryPanel.js.map +1 -1
- package/dist/client/history/index.d.ts +1 -1
- package/dist/client/history/index.d.ts.map +1 -1
- package/dist/client/history/index.js +1 -1
- package/dist/client/history/index.js.map +1 -1
- package/dist/client/history/use-history.d.ts +12 -0
- package/dist/client/history/use-history.d.ts.map +1 -1
- package/dist/client/history/use-history.js +6 -0
- package/dist/client/history/use-history.js.map +1 -1
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/review/index.d.ts +1 -1
- package/dist/client/review/index.d.ts.map +1 -1
- package/dist/client/review/index.js +1 -1
- package/dist/client/review/index.js.map +1 -1
- package/dist/client/review/use-review.d.ts +23 -0
- package/dist/client/review/use-review.d.ts.map +1 -1
- package/dist/client/review/use-review.js +8 -0
- package/dist/client/review/use-review.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/history/actions/create-resource-version.js +7 -4
- package/dist/history/actions/create-resource-version.js.map +1 -1
- package/dist/history/index.d.ts +1 -1
- package/dist/history/index.d.ts.map +1 -1
- package/dist/history/index.js +1 -1
- package/dist/history/index.js.map +1 -1
- package/dist/history/registry.d.ts.map +1 -1
- package/dist/history/registry.js +14 -12
- package/dist/history/registry.js.map +1 -1
- package/dist/history/store.d.ts.map +1 -1
- package/dist/history/store.js +74 -49
- package/dist/history/store.js.map +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/review/actions/consume-review-feedback.d.ts +1 -0
- package/dist/review/actions/consume-review-feedback.js +8 -2
- package/dist/review/actions/consume-review-feedback.js.map +1 -1
- package/dist/review/actions/delete-review-comment.d.ts +2 -1
- package/dist/review/actions/delete-review-comment.js +11 -3
- package/dist/review/actions/delete-review-comment.js.map +1 -1
- package/dist/review/actions/resolve-review-thread.d.ts +2 -1
- package/dist/review/actions/resolve-review-thread.js +5 -2
- package/dist/review/actions/resolve-review-thread.js.map +1 -1
- package/dist/review/index.d.ts +1 -1
- package/dist/review/index.d.ts.map +1 -1
- package/dist/review/index.js +1 -1
- package/dist/review/index.js.map +1 -1
- package/dist/review/registry.d.ts.map +1 -1
- package/dist/review/registry.js +14 -12
- package/dist/review/registry.js.map +1 -1
- package/dist/review/store.d.ts +3 -3
- package/dist/review/store.d.ts.map +1 -1
- package/dist/review/store.js +7 -4
- package/dist/review/store.js.map +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +5 -0
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/credential-provider.d.ts +2 -0
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +13 -3
- package/dist/server/credential-provider.js.map +1 -1
- package/package.json +1 -1
|
@@ -137,7 +137,11 @@ const enUS = {
|
|
|
137
137
|
contacts: "Contacts",
|
|
138
138
|
contactsReconnect: "Contacts or directory access needs to be reconnected.",
|
|
139
139
|
directory: "Directory",
|
|
140
|
+
guestOptions: "Guest options for {{email}}",
|
|
140
141
|
inviteEmail: "Invite {{email}}",
|
|
142
|
+
markOptional: "Mark as optional",
|
|
143
|
+
markRequired: "Mark as required",
|
|
144
|
+
optionalBadge: "Optional",
|
|
141
145
|
otherContacts: "Other contacts",
|
|
142
146
|
removeAttendee: "Remove {{email}}",
|
|
143
147
|
searchingPeople: "Searching people",
|
|
@@ -6122,7 +6126,11 @@ const translatedCalendarRemainingRaw = {
|
|
|
6122
6126
|
contacts: "联系人",
|
|
6123
6127
|
contactsReconnect: "需要重新连接联系人或目录访问权限。",
|
|
6124
6128
|
directory: "目录",
|
|
6129
|
+
guestOptions: "{{email}} 的来宾选项",
|
|
6125
6130
|
inviteEmail: "邀请 {{email}}",
|
|
6131
|
+
markOptional: "标为可选",
|
|
6132
|
+
markRequired: "标为必选",
|
|
6133
|
+
optionalBadge: "可选",
|
|
6126
6134
|
otherContacts: "其他联系人",
|
|
6127
6135
|
removeAttendee: "移除 {{email}}",
|
|
6128
6136
|
searchingPeople: "正在搜索人员",
|
|
@@ -6238,7 +6246,11 @@ const translatedCalendarRemainingRaw = {
|
|
|
6238
6246
|
contactsReconnect:
|
|
6239
6247
|
"Hay que volver a conectar el acceso a contactos o directorio.",
|
|
6240
6248
|
directory: "Directorio",
|
|
6249
|
+
guestOptions: "Opciones de invitado para {{email}}",
|
|
6241
6250
|
inviteEmail: "Invitar a {{email}}",
|
|
6251
|
+
markOptional: "Marcar como opcional",
|
|
6252
|
+
markRequired: "Marcar como obligatorio",
|
|
6253
|
+
optionalBadge: "Opcional",
|
|
6242
6254
|
otherContacts: "Otros contactos",
|
|
6243
6255
|
removeAttendee: "Quitar {{email}}",
|
|
6244
6256
|
searchingPeople: "Buscando personas",
|
|
@@ -6578,7 +6590,11 @@ const translatedCalendarExactCleanup = {
|
|
|
6578
6590
|
contactsReconnect:
|
|
6579
6591
|
"L’accès aux contacts ou à l’annuaire doit être reconnecté.",
|
|
6580
6592
|
directory: "Annuaire",
|
|
6593
|
+
guestOptions: "Options d’invité pour {{email}}",
|
|
6581
6594
|
inviteEmail: "Inviter {{email}}",
|
|
6595
|
+
markOptional: "Marquer comme facultatif",
|
|
6596
|
+
markRequired: "Marquer comme obligatoire",
|
|
6597
|
+
optionalBadge: "Facultatif",
|
|
6582
6598
|
otherContacts: "Autres contacts",
|
|
6583
6599
|
removeAttendee: "Retirer {{email}}",
|
|
6584
6600
|
searchingPeople: "Recherche de personnes",
|
|
@@ -6763,7 +6779,11 @@ const translatedCalendarExactCleanup = {
|
|
|
6763
6779
|
contactsReconnect:
|
|
6764
6780
|
"Kontakte oder Verzeichniszugriff müssen erneut verbunden werden.",
|
|
6765
6781
|
directory: "Verzeichnis",
|
|
6782
|
+
guestOptions: "Gastoptionen für {{email}}",
|
|
6766
6783
|
inviteEmail: "{{email}} einladen",
|
|
6784
|
+
markOptional: "Als optional markieren",
|
|
6785
|
+
markRequired: "Als erforderlich markieren",
|
|
6786
|
+
optionalBadge: "Optional",
|
|
6767
6787
|
otherContacts: "Weitere Kontakte",
|
|
6768
6788
|
removeAttendee: "{{email}} entfernen",
|
|
6769
6789
|
searchingPeople: "Personen werden gesucht",
|
|
@@ -6938,7 +6958,11 @@ const translatedCalendarExactCleanup = {
|
|
|
6938
6958
|
contacts: "連絡先",
|
|
6939
6959
|
contactsReconnect: "連絡先またはディレクトリアクセスの再接続が必要です。",
|
|
6940
6960
|
directory: "ディレクトリ",
|
|
6961
|
+
guestOptions: "{{email}} のゲストオプション",
|
|
6941
6962
|
inviteEmail: "{{email}} を招待",
|
|
6963
|
+
markOptional: "任意出席者にする",
|
|
6964
|
+
markRequired: "必須出席者にする",
|
|
6965
|
+
optionalBadge: "任意",
|
|
6942
6966
|
otherContacts: "その他の連絡先",
|
|
6943
6967
|
removeAttendee: "{{email}} を削除",
|
|
6944
6968
|
searchingPeople: "ユーザーを検索中",
|
|
@@ -7104,7 +7128,11 @@ const translatedCalendarExactCleanup = {
|
|
|
7104
7128
|
contacts: "연락처",
|
|
7105
7129
|
contactsReconnect: "연락처 또는 디렉터리 액세스를 다시 연결해야 합니다.",
|
|
7106
7130
|
directory: "디렉터리",
|
|
7131
|
+
guestOptions: "{{email}} 게스트 옵션",
|
|
7107
7132
|
inviteEmail: "{{email}} 초대",
|
|
7133
|
+
markOptional: "선택으로 표시",
|
|
7134
|
+
markRequired: "필수로 표시",
|
|
7135
|
+
optionalBadge: "선택",
|
|
7108
7136
|
otherContacts: "기타 연락처",
|
|
7109
7137
|
removeAttendee: "{{email}} 제거",
|
|
7110
7138
|
searchingPeople: "사람 검색 중",
|
|
@@ -7279,7 +7307,11 @@ const translatedCalendarExactCleanup = {
|
|
|
7279
7307
|
contactsReconnect:
|
|
7280
7308
|
"O acesso a contatos ou diretório precisa ser reconectado.",
|
|
7281
7309
|
directory: "Diretório",
|
|
7310
|
+
guestOptions: "Opções de convidado para {{email}}",
|
|
7282
7311
|
inviteEmail: "Convidar {{email}}",
|
|
7312
|
+
markOptional: "Marcar como opcional",
|
|
7313
|
+
markRequired: "Marcar como obrigatório",
|
|
7314
|
+
optionalBadge: "Opcional",
|
|
7283
7315
|
otherContacts: "Outros contatos",
|
|
7284
7316
|
removeAttendee: "Remover {{email}}",
|
|
7285
7317
|
searchingPeople: "Pesquisando pessoas",
|
|
@@ -7454,7 +7486,11 @@ const translatedCalendarExactCleanup = {
|
|
|
7454
7486
|
contacts: "संपर्क",
|
|
7455
7487
|
contactsReconnect: "संपर्क या डायरेक्टरी एक्सेस को फिर से कनेक्ट करना होगा।",
|
|
7456
7488
|
directory: "डायरेक्टरी",
|
|
7489
|
+
guestOptions: "{{email}} के लिए अतिथि विकल्प",
|
|
7457
7490
|
inviteEmail: "{{email}} को आमंत्रित करें",
|
|
7491
|
+
markOptional: "वैकल्पिक के रूप में चिह्नित करें",
|
|
7492
|
+
markRequired: "आवश्यक के रूप में चिह्नित करें",
|
|
7493
|
+
optionalBadge: "वैकल्पिक",
|
|
7458
7494
|
otherContacts: "अन्य संपर्क",
|
|
7459
7495
|
removeAttendee: "{{email}} हटाएं",
|
|
7460
7496
|
searchingPeople: "लोग खोजे जा रहे हैं",
|
|
@@ -7624,7 +7660,11 @@ const translatedCalendarExactCleanup = {
|
|
|
7624
7660
|
contacts: "جهات الاتصال",
|
|
7625
7661
|
contactsReconnect: "يلزم إعادة توصيل الوصول إلى جهات الاتصال أو الدليل.",
|
|
7626
7662
|
directory: "الدليل",
|
|
7663
|
+
guestOptions: "خيارات الضيف لـ {{email}}",
|
|
7627
7664
|
inviteEmail: "دعوة {{email}}",
|
|
7665
|
+
markOptional: "تعيين كاختياري",
|
|
7666
|
+
markRequired: "تعيين كإلزامي",
|
|
7667
|
+
optionalBadge: "اختياري",
|
|
7628
7668
|
otherContacts: "جهات اتصال أخرى",
|
|
7629
7669
|
removeAttendee: "إزالة {{email}}",
|
|
7630
7670
|
searchingPeople: "جارٍ البحث عن أشخاص",
|
|
@@ -181,6 +181,7 @@ export const getEvent = defineEventHandler(async (event: H3Event) => {
|
|
|
181
181
|
responseStatus: a.responseStatus || undefined,
|
|
182
182
|
organizer: a.organizer || undefined,
|
|
183
183
|
self: a.self || undefined,
|
|
184
|
+
optional: a.optional === true ? true : undefined,
|
|
184
185
|
})),
|
|
185
186
|
remindersUseDefault: evt.reminders?.useDefault ?? true,
|
|
186
187
|
reminders: evt.reminders?.overrides?.map((r: any) => ({
|
|
@@ -228,6 +228,7 @@ function mapAttendees(event: any): CalendarEvent["attendees"] {
|
|
|
228
228
|
responseStatus: attendee.responseStatus || undefined,
|
|
229
229
|
organizer: attendee.organizer || undefined,
|
|
230
230
|
self: attendee.self || undefined,
|
|
231
|
+
optional: attendee.optional === true ? true : undefined,
|
|
231
232
|
}));
|
|
232
233
|
}
|
|
233
234
|
|
|
@@ -1094,6 +1095,7 @@ export async function createEvent(
|
|
|
1094
1095
|
email: a.email,
|
|
1095
1096
|
...(a.displayName ? { displayName: a.displayName } : {}),
|
|
1096
1097
|
...(a.comment ? { comment: a.comment } : {}),
|
|
1098
|
+
...(a.optional === true ? { optional: true } : {}),
|
|
1097
1099
|
}));
|
|
1098
1100
|
}
|
|
1099
1101
|
|
|
@@ -1204,6 +1206,7 @@ export async function updateEvent(
|
|
|
1204
1206
|
...(a.displayName ? { displayName: a.displayName } : {}),
|
|
1205
1207
|
...(a.comment ? { comment: a.comment } : {}),
|
|
1206
1208
|
...(a.responseStatus ? { responseStatus: a.responseStatus } : {}),
|
|
1209
|
+
...(a.optional === true ? { optional: true } : { optional: false }),
|
|
1207
1210
|
}));
|
|
1208
1211
|
}
|
|
1209
1212
|
if (eventPatch.recurrence !== undefined) {
|
|
@@ -1241,6 +1244,7 @@ export async function updateEvent(
|
|
|
1241
1244
|
responseStatus: a.responseStatus || undefined,
|
|
1242
1245
|
organizer: a.organizer || undefined,
|
|
1243
1246
|
self: a.self || undefined,
|
|
1247
|
+
optional: a.optional === true ? true : undefined,
|
|
1244
1248
|
})),
|
|
1245
1249
|
};
|
|
1246
1250
|
}
|
|
@@ -107,7 +107,7 @@ Provider-specific Calendar actions are shortcuts, not limits. If a first-class a
|
|
|
107
107
|
- \`pnpm action search-events --query "term" --from YYYY-MM-DD --to YYYY-MM-DD\` — Convenience bounded search by title, attendees, organizer, location, or description. For relationship history, all-calendar discovery, exact attendee/domain search, or custom pagination, prefer provider-api-request with provider=google_calendar.
|
|
108
108
|
- \`pnpm action provider-api-catalog\` / \`provider-api-docs\` / \`provider-api-request\` — Inspect and call the real Google Calendar, Apollo, Gong, HubSpot, and Pylon APIs directly. For Google Calendar events.list pagination use provider=google_calendar, path=/calendars/primary/events, query={...}, fetchAllPages={cursorPath:"nextPageToken",cursorParam:"pageToken",itemsPath:"items"}. For large relationship-history scans, pass stageAs and pagination={nextCursorPath:"nextPageToken",cursorParam:"pageToken",maxPages:N} with itemsPath="items", then use query-staged-dataset.
|
|
109
109
|
- \`pnpm action create-event --title "..." --start "ISO" --end "ISO"\` — Create a new event. Use \`--eventType outOfOffice\` for OOO, \`--eventType focusTime\` for focus time, \`--eventType workingLocation\` for working location, \`--transparency transparent\` to show as Free, \`--visibility private\` for private events, \`--startTimeZone America/Los_Angeles\` for timezone anchoring, \`--colorId 9\` for Google event color, \`--reminders '[{"method":"popup","minutes":10}]'\` for alerts, and \`--attachments '[{"fileUrl":"https://...","title":"Agenda"}]'\` for Drive/HTTPS file links.
|
|
110
|
-
- \`pnpm action update-event --id "google-..." --transparency opaque|transparent --visibility default|public|private --reminderMinutes 10 --addAttendees "alice@example.com" --scope single|all\` — Update event availability, visibility, reminders, timezone, color, attachments, recurrence, guests, or generated video links. Use \`addAttendees\` when inviting more people so existing RSVP metadata is preserved. Use \`--scope all\` to update an entire recurring series from one occurrence.
|
|
110
|
+
- \`pnpm action update-event --id "google-..." --transparency opaque|transparent --visibility default|public|private --reminderMinutes 10 --addAttendees "alice@example.com" --scope single|all\` — Update event availability, visibility, reminders, timezone, color, attachments, recurrence, guests, or generated video links. Use \`addAttendees\` when inviting more people so existing RSVP metadata is preserved. Pass attendee objects with \`optional:true\` to mark optional guests. Use \`--scope all\` to update an entire recurring series from one occurrence.
|
|
111
111
|
- \`pnpm action navigate --view=calendar --calendarViewMode=day\` — Navigate the UI (day/week/month views, dates)
|
|
112
112
|
- \`pnpm action navigate --view=calendar --date=YYYY-MM-DD\` — Navigate to a specific date
|
|
113
113
|
- \`pnpm action navigate --view=availability\` — Show availability settings
|
|
@@ -45,6 +45,8 @@ export interface CalendarEvent {
|
|
|
45
45
|
responseStatus?: "accepted" | "declined" | "tentative" | "needsAction";
|
|
46
46
|
organizer?: boolean;
|
|
47
47
|
self?: boolean;
|
|
48
|
+
/** When true, the attendee is optional (Google Calendar `optional`). */
|
|
49
|
+
optional?: boolean;
|
|
48
50
|
}>;
|
|
49
51
|
reminders?: Array<{ method: "popup" | "email"; minutes: number }>;
|
|
50
52
|
/** Whether this event uses the calendar's default reminder policy. */
|
|
@@ -27,15 +27,41 @@ The agent is already the user's primary interface — it has full project contex
|
|
|
27
27
|
|
|
28
28
|
| Feature | Trigger | What the action does |
|
|
29
29
|
| ------------------------- | ------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
30
|
-
|
|
|
30
|
+
| Include full video | User toggles "Include full video" in the AI tools menu | `update-clips-ai-prefs --includeFullVideoInAi=true\|false` → stored in `clips-user-prefs`; default off |
|
|
31
|
+
| Default title | Native transcript is saved and the recording still has the default title | `regenerate-title --recordingId=<id>` → writes `clips-ai-request-:id`; the UI bridge sends it to the agent chat. If Include full video is on, skips the transcript-only Gemini fast path and always delegates so the agent watches the recording |
|
|
31
32
|
| Manual title suggestion | User asks the agent "rename this" | Agent reads transcript and calls `update-recording --id=<id> --title=...` |
|
|
32
|
-
| Summary / description | Upload completes, or user clicks "Summarize"
|
|
33
|
-
| Chapters | User clicks "Add chapters" or transcript > 3 minutes | `generate-chapters --id=<id>` → agent writes `chapters_json`
|
|
33
|
+
| Summary / description | Upload completes, or user clicks "Summarize" / "Regenerate description" | `regenerate-summary` / `generate-ai-metadata --id=<id> --kind=summary` → agent writes `update-recording --description=...`. With Include full video, agent must watch the clip, not transcript alone |
|
|
34
|
+
| Chapters | User clicks "Add chapters" or transcript > 3 minutes | `generate-chapters --id=<id>` / `regenerate-chapters` → agent writes `chapters_json` (same full-video preference) |
|
|
34
35
|
| Tags | On upload complete | `generate-ai-metadata --id=<id> --kind=tags` → agent inserts `recording_tags` rows |
|
|
35
36
|
| Filler-word removal | User clicks "Remove ums and uhs" | `generate-filler-removal --id=<id>` → agent writes proposed cuts into `editor-draft` for user review |
|
|
36
37
|
| Comment auto-reply | User types "reply with …" in the agent chat | agent calls `add-comment` directly |
|
|
37
38
|
| **Transcription** | On upload complete (automatic) + live during recording | `request-transcript` → native (Web Speech / macOS SFSpeech) first, then cloud fallback Builder.io managed Gemini → Groq; `save-browser-transcript` for instant Web Speech result — see "Transcription" section below |
|
|
38
39
|
|
|
40
|
+
## Include full video
|
|
41
|
+
|
|
42
|
+
Screen recordings often have thin or misleading audio ("real quick", "um this
|
|
43
|
+
thing"). Titles, descriptions, chapters, and workflow docs (PR / SOP / ticket /
|
|
44
|
+
email) are more accurate when the agent can **see** the UI, product names, and
|
|
45
|
+
on-screen text.
|
|
46
|
+
|
|
47
|
+
- Preference key: `includeFullVideoInAi` on user setting `clips-user-prefs`.
|
|
48
|
+
- UI: checkbox at the top of the recording-page **AI tools** dropdown (copy
|
|
49
|
+
notes Gemini-only).
|
|
50
|
+
- Actions: `get-clips-ai-prefs`, `update-clips-ai-prefs`.
|
|
51
|
+
- **Gemini only:** sending / understanding the full recording video requires a
|
|
52
|
+
Gemini model (Builder Gemini or `GEMINI_API_KEY`). Claude and OpenAI cannot
|
|
53
|
+
ingest the MP4/WebM. When the preference is on, the AI-request bridge prefers
|
|
54
|
+
Builder `gemini-3-5-flash` for that turn.
|
|
55
|
+
- When on, queued `clips-ai-request-*` messages include instructions to attach
|
|
56
|
+
or upload the recording to Gemini when possible, otherwise use
|
|
57
|
+
`get-recording-player-data` / `create-recording-agent-link` and follow
|
|
58
|
+
recommended frames / the frame API across the timeline — not transcript only.
|
|
59
|
+
- Default title generation also honors this: `regenerate-title` skips the
|
|
60
|
+
transcript-only Gemini cleanup path and always queues the agent.
|
|
61
|
+
|
|
62
|
+
Do not invent a parallel "video LLM" path in the UI. Keep the preference on the
|
|
63
|
+
shared user-prefs object and keep delegation through the agent chat.
|
|
64
|
+
|
|
39
65
|
## The delegation pattern
|
|
40
66
|
|
|
41
67
|
From an action, kick work over to the agent chat in **background mode** so the user doesn't see a new message bubble mid-playback:
|
|
@@ -21,6 +21,8 @@ import { eq } from "drizzle-orm";
|
|
|
21
21
|
import { z } from "zod";
|
|
22
22
|
|
|
23
23
|
import { getDb, schema } from "../server/db/index.js";
|
|
24
|
+
import { withFullVideoAiInstructions } from "../shared/clips-ai-prefs.js";
|
|
25
|
+
import { readIncludeFullVideoInAi } from "./lib/clips-ai-prefs.js";
|
|
24
26
|
|
|
25
27
|
const KIND_PROMPTS = {
|
|
26
28
|
pr: `Compose a pull-request description. Include:
|
|
@@ -51,7 +53,7 @@ Keep it concise, warm, and professional.`,
|
|
|
51
53
|
|
|
52
54
|
export default defineAction({
|
|
53
55
|
description:
|
|
54
|
-
"Ask the agent to generate a structured workflow doc (pr/sop/ticket/email) from this recording's transcript. The agent writes the result to clips-workflow-<recordingId> in application_state.",
|
|
56
|
+
"Ask the agent to generate a structured workflow doc (pr/sop/ticket/email) from this recording's transcript (and the full video when Include full video is enabled). The agent writes the result to clips-workflow-<recordingId> in application_state.",
|
|
55
57
|
schema: z.object({
|
|
56
58
|
recordingId: z.string().describe("Recording ID"),
|
|
57
59
|
kind: z.enum(["pr", "sop", "ticket", "email"]).describe("Workflow kind"),
|
|
@@ -74,6 +76,7 @@ export default defineAction({
|
|
|
74
76
|
.limit(1);
|
|
75
77
|
|
|
76
78
|
const stateKey = `clips-workflow-${args.recordingId}`;
|
|
79
|
+
const includeFullVideoInAi = await readIncludeFullVideoInAi();
|
|
77
80
|
|
|
78
81
|
// Seed the output state with a "generating" placeholder so the UI can show
|
|
79
82
|
// a loading state immediately.
|
|
@@ -84,6 +87,14 @@ export default defineAction({
|
|
|
84
87
|
requestedAt: new Date().toISOString(),
|
|
85
88
|
} as any);
|
|
86
89
|
|
|
90
|
+
const baseMessage =
|
|
91
|
+
`Generate a ${args.kind.toUpperCase()} workflow document from recording ${args.recordingId} ` +
|
|
92
|
+
`(title: "${rec.title}"). Read the transcript from this request's context. ` +
|
|
93
|
+
`${KIND_PROMPTS[args.kind]} ` +
|
|
94
|
+
`Then write the final markdown to application_state key "${stateKey}" as ` +
|
|
95
|
+
`\`{ kind: "${args.kind}", status: "ready", content: "...", recordingId: "${args.recordingId}" }\`. ` +
|
|
96
|
+
`Finish by replying in chat with the same generated markdown so the user can read it immediately.`;
|
|
97
|
+
|
|
87
98
|
const request = {
|
|
88
99
|
kind: "generate-workflow" as const,
|
|
89
100
|
workflowKind: args.kind,
|
|
@@ -95,13 +106,12 @@ export default defineAction({
|
|
|
95
106
|
transcriptText: transcript?.fullText ?? "",
|
|
96
107
|
stateKey,
|
|
97
108
|
instructions: KIND_PROMPTS[args.kind],
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
`Finish by replying in chat with the same generated markdown so the user can read it immediately.`,
|
|
109
|
+
includeFullVideoInAi,
|
|
110
|
+
message: withFullVideoAiInstructions(
|
|
111
|
+
baseMessage,
|
|
112
|
+
args.recordingId,
|
|
113
|
+
includeFullVideoInAi,
|
|
114
|
+
),
|
|
105
115
|
};
|
|
106
116
|
|
|
107
117
|
await writeAppState(`clips-ai-request-${args.recordingId}`, request as any);
|
|
@@ -115,6 +125,7 @@ export default defineAction({
|
|
|
115
125
|
recordingId: args.recordingId,
|
|
116
126
|
kind: args.kind,
|
|
117
127
|
stateKey,
|
|
128
|
+
includeFullVideoInAi,
|
|
118
129
|
};
|
|
119
130
|
},
|
|
120
131
|
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read Clips AI preferences for the current user (include-full-video switch).
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* pnpm action get-clips-ai-prefs
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { defineAction } from "@agent-native/core";
|
|
9
|
+
import { getRequestUserEmail } from "@agent-native/core/server/request-context";
|
|
10
|
+
import { getUserSetting } from "@agent-native/core/settings";
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
CLIPS_USER_PREFS_KEY,
|
|
15
|
+
isIncludeFullVideoInAiEnabled,
|
|
16
|
+
type ClipsUserPrefs,
|
|
17
|
+
} from "../shared/clips-ai-prefs.js";
|
|
18
|
+
|
|
19
|
+
export default defineAction({
|
|
20
|
+
description:
|
|
21
|
+
"Get Clips AI tool preferences for the current user, including whether AI tools should watch the full recording with Gemini instead of transcript-only.",
|
|
22
|
+
schema: z.object({}),
|
|
23
|
+
http: { method: "GET" },
|
|
24
|
+
readOnly: true,
|
|
25
|
+
run: async () => {
|
|
26
|
+
const email = getRequestUserEmail();
|
|
27
|
+
if (!email) {
|
|
28
|
+
return { includeFullVideoInAi: false };
|
|
29
|
+
}
|
|
30
|
+
const prefs = ((await getUserSetting(email, CLIPS_USER_PREFS_KEY)) ??
|
|
31
|
+
{}) as ClipsUserPrefs;
|
|
32
|
+
return {
|
|
33
|
+
includeFullVideoInAi: isIncludeFullVideoInAiEnabled(prefs),
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server helper: load the current user's "include full video in AI" preference.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { getRequestUserEmail } from "@agent-native/core/server/request-context";
|
|
6
|
+
import { getUserSetting } from "@agent-native/core/settings";
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
CLIPS_USER_PREFS_KEY,
|
|
10
|
+
isIncludeFullVideoInAiEnabled,
|
|
11
|
+
type ClipsUserPrefs,
|
|
12
|
+
} from "../../shared/clips-ai-prefs.js";
|
|
13
|
+
|
|
14
|
+
export async function readIncludeFullVideoInAi(
|
|
15
|
+
email?: string | null,
|
|
16
|
+
): Promise<boolean> {
|
|
17
|
+
const userEmail = email ?? getRequestUserEmail();
|
|
18
|
+
if (!userEmail) return false;
|
|
19
|
+
try {
|
|
20
|
+
const prefs = (await getUserSetting(
|
|
21
|
+
userEmail,
|
|
22
|
+
CLIPS_USER_PREFS_KEY,
|
|
23
|
+
)) as ClipsUserPrefs | null;
|
|
24
|
+
return isIncludeFullVideoInAiEnabled(prefs);
|
|
25
|
+
} catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -15,10 +15,12 @@ import { eq } from "drizzle-orm";
|
|
|
15
15
|
import { z } from "zod";
|
|
16
16
|
|
|
17
17
|
import { getDb, schema } from "../server/db/index.js";
|
|
18
|
+
import { withFullVideoAiInstructions } from "../shared/clips-ai-prefs.js";
|
|
19
|
+
import { readIncludeFullVideoInAi } from "./lib/clips-ai-prefs.js";
|
|
18
20
|
|
|
19
21
|
export default defineAction({
|
|
20
22
|
description:
|
|
21
|
-
"Ask the agent to generate chapters for this recording based on its transcript. The agent identifies topic transitions and calls set-chapters.",
|
|
23
|
+
"Ask the agent to generate chapters for this recording based on its transcript (and the full video when Include full video is enabled). The agent identifies topic transitions and calls set-chapters.",
|
|
22
24
|
schema: z.object({
|
|
23
25
|
recordingId: z.string().describe("Recording ID"),
|
|
24
26
|
}),
|
|
@@ -39,6 +41,13 @@ export default defineAction({
|
|
|
39
41
|
.where(eq(schema.recordingTranscripts.recordingId, args.recordingId))
|
|
40
42
|
.limit(1);
|
|
41
43
|
|
|
44
|
+
const includeFullVideoInAi = await readIncludeFullVideoInAi();
|
|
45
|
+
const baseMessage =
|
|
46
|
+
`Generate chapters for recording ${args.recordingId} (duration ${rec.durationMs}ms). ` +
|
|
47
|
+
`Read the transcript segments in this request's context, identify topic transitions, ` +
|
|
48
|
+
`and call \`set-chapters --recordingId=${args.recordingId} --chapters='[{ "startMs": 0, "title": "Intro" }, ...]'\`. ` +
|
|
49
|
+
`Aim for 3–8 chapters. Each chapter title should be 3–6 words and capture the essence of that section.`;
|
|
50
|
+
|
|
42
51
|
const request = {
|
|
43
52
|
kind: "regenerate-chapters" as const,
|
|
44
53
|
recordingId: args.recordingId,
|
|
@@ -47,11 +56,12 @@ export default defineAction({
|
|
|
47
56
|
transcriptStatus: transcript?.status ?? "pending",
|
|
48
57
|
segmentsJson: transcript?.segmentsJson ?? "[]",
|
|
49
58
|
transcriptText: transcript?.fullText ?? "",
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
59
|
+
includeFullVideoInAi,
|
|
60
|
+
message: withFullVideoAiInstructions(
|
|
61
|
+
baseMessage,
|
|
62
|
+
args.recordingId,
|
|
63
|
+
includeFullVideoInAi,
|
|
64
|
+
),
|
|
55
65
|
};
|
|
56
66
|
|
|
57
67
|
await writeAppState(`clips-ai-request-${args.recordingId}`, request as any);
|
|
@@ -60,6 +70,10 @@ export default defineAction({
|
|
|
60
70
|
console.log(
|
|
61
71
|
`Delegation queued: regenerate-chapters for ${args.recordingId}`,
|
|
62
72
|
);
|
|
63
|
-
return {
|
|
73
|
+
return {
|
|
74
|
+
queued: true,
|
|
75
|
+
recordingId: args.recordingId,
|
|
76
|
+
includeFullVideoInAi,
|
|
77
|
+
};
|
|
64
78
|
},
|
|
65
79
|
});
|
|
@@ -14,10 +14,12 @@ import { eq } from "drizzle-orm";
|
|
|
14
14
|
import { z } from "zod";
|
|
15
15
|
|
|
16
16
|
import { getDb, schema } from "../server/db/index.js";
|
|
17
|
+
import { withFullVideoAiInstructions } from "../shared/clips-ai-prefs.js";
|
|
18
|
+
import { readIncludeFullVideoInAi } from "./lib/clips-ai-prefs.js";
|
|
17
19
|
|
|
18
20
|
export default defineAction({
|
|
19
21
|
description:
|
|
20
|
-
"Ask the agent to regenerate this recording's description/summary based on its transcript.",
|
|
22
|
+
"Ask the agent to regenerate this recording's description/summary based on its transcript (and the full video when Include full video is enabled).",
|
|
21
23
|
schema: z.object({
|
|
22
24
|
recordingId: z.string().describe("Recording ID"),
|
|
23
25
|
}),
|
|
@@ -42,7 +44,12 @@ export default defineAction({
|
|
|
42
44
|
.where(eq(schema.recordingTranscripts.recordingId, args.recordingId))
|
|
43
45
|
.limit(1);
|
|
44
46
|
|
|
45
|
-
|
|
47
|
+
const includeFullVideoInAi = await readIncludeFullVideoInAi();
|
|
48
|
+
|
|
49
|
+
if (
|
|
50
|
+
!includeFullVideoInAi &&
|
|
51
|
+
(transcript?.status !== "ready" || !transcript.fullText?.trim())
|
|
52
|
+
) {
|
|
46
53
|
return {
|
|
47
54
|
updated: false,
|
|
48
55
|
skipped: true,
|
|
@@ -52,6 +59,12 @@ export default defineAction({
|
|
|
52
59
|
};
|
|
53
60
|
}
|
|
54
61
|
|
|
62
|
+
const baseMessage =
|
|
63
|
+
`Regenerate the description for recording ${args.recordingId}. ` +
|
|
64
|
+
`Read the transcript in this request's context and call ` +
|
|
65
|
+
`\`update-recording --id=${args.recordingId} --description="..."\` with a 2–4 ` +
|
|
66
|
+
`sentence summary of what the recording covers. Title: "${rec.title}".`;
|
|
67
|
+
|
|
55
68
|
const request = {
|
|
56
69
|
kind: "regenerate-summary" as const,
|
|
57
70
|
recordingId: args.recordingId,
|
|
@@ -60,11 +73,12 @@ export default defineAction({
|
|
|
60
73
|
currentDescription: rec.description,
|
|
61
74
|
transcriptStatus: transcript?.status ?? "pending",
|
|
62
75
|
transcriptText: transcript?.fullText ?? "",
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
76
|
+
includeFullVideoInAi,
|
|
77
|
+
message: withFullVideoAiInstructions(
|
|
78
|
+
baseMessage,
|
|
79
|
+
args.recordingId,
|
|
80
|
+
includeFullVideoInAi,
|
|
81
|
+
),
|
|
68
82
|
};
|
|
69
83
|
|
|
70
84
|
await writeAppState(`clips-ai-request-${args.recordingId}`, request as any);
|
|
@@ -73,6 +87,10 @@ export default defineAction({
|
|
|
73
87
|
console.log(
|
|
74
88
|
`Delegation queued: regenerate-summary for ${args.recordingId}`,
|
|
75
89
|
);
|
|
76
|
-
return {
|
|
90
|
+
return {
|
|
91
|
+
queued: true,
|
|
92
|
+
recordingId: args.recordingId,
|
|
93
|
+
includeFullVideoInAi,
|
|
94
|
+
};
|
|
77
95
|
},
|
|
78
96
|
});
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
* waiting for the agent chat bridge. If the fast path is unavailable, we still
|
|
7
7
|
* queue the older agent-chat request as a fallback.
|
|
8
8
|
*
|
|
9
|
+
* When the user enables Include full video, we skip the transcript-only fast
|
|
10
|
+
* path and always delegate so the agent can watch the recording.
|
|
11
|
+
*
|
|
9
12
|
* Usage:
|
|
10
13
|
* pnpm action regenerate-title --recordingId=<id>
|
|
11
14
|
*/
|
|
@@ -19,9 +22,11 @@ import { z } from "zod";
|
|
|
19
22
|
|
|
20
23
|
import { getDb, schema } from "../server/db/index.js";
|
|
21
24
|
import { isBuilderCreditsExhaustedMessage } from "../shared/builder-credits.js";
|
|
25
|
+
import { withFullVideoAiInstructions } from "../shared/clips-ai-prefs.js";
|
|
22
26
|
import cleanupTranscript from "./cleanup-transcript.js";
|
|
23
27
|
import { loadAgentsMdContext } from "./lib/agents-md-context.js";
|
|
24
28
|
import { clearBuilderCreditsExhausted } from "./lib/builder-credits-state.js";
|
|
29
|
+
import { readIncludeFullVideoInAi } from "./lib/clips-ai-prefs.js";
|
|
25
30
|
import {
|
|
26
31
|
cleanGeneratedTitle,
|
|
27
32
|
fallbackTitleFromTranscript,
|
|
@@ -66,6 +71,7 @@ export async function queueTitleRegenerationRequest({
|
|
|
66
71
|
transcriptStatus = "ready",
|
|
67
72
|
segmentsJson = "[]",
|
|
68
73
|
ownerEmail,
|
|
74
|
+
includeFullVideoInAi,
|
|
69
75
|
}: {
|
|
70
76
|
recordingId: string;
|
|
71
77
|
currentTitle: string | null | undefined;
|
|
@@ -73,11 +79,20 @@ export async function queueTitleRegenerationRequest({
|
|
|
73
79
|
transcriptStatus?: string;
|
|
74
80
|
segmentsJson?: string | null;
|
|
75
81
|
ownerEmail?: string | null;
|
|
82
|
+
includeFullVideoInAi?: boolean;
|
|
76
83
|
}) {
|
|
77
84
|
const agentsContext = await loadAgentsMdContext({
|
|
78
85
|
ownerEmail,
|
|
79
86
|
purpose: "title",
|
|
80
87
|
});
|
|
88
|
+
const useVideo =
|
|
89
|
+
includeFullVideoInAi ?? (await readIncludeFullVideoInAi(ownerEmail));
|
|
90
|
+
const baseMessage =
|
|
91
|
+
`Regenerate the title for recording ${recordingId}. ` +
|
|
92
|
+
`Read the native transcript and AGENTS.md context in this request's context and call ` +
|
|
93
|
+
`\`update-recording --id=${recordingId} --title="..."\` with a concise ` +
|
|
94
|
+
`4-9 word descriptive title. Current title: "${currentTitle ?? ""}". ` +
|
|
95
|
+
"Do not prompt the user.";
|
|
81
96
|
const request = {
|
|
82
97
|
kind: "regenerate-title" as const,
|
|
83
98
|
recordingId,
|
|
@@ -87,12 +102,8 @@ export async function queueTitleRegenerationRequest({
|
|
|
87
102
|
transcriptText,
|
|
88
103
|
segmentsJson: segmentsJson ?? "[]",
|
|
89
104
|
agentsContext,
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
`Read the native transcript and AGENTS.md context in this request's context and call ` +
|
|
93
|
-
`\`update-recording --id=${recordingId} --title="..."\` with a concise ` +
|
|
94
|
-
`4-9 word descriptive title. Current title: "${currentTitle ?? ""}". ` +
|
|
95
|
-
"Do not prompt the user.",
|
|
105
|
+
includeFullVideoInAi: useVideo,
|
|
106
|
+
message: withFullVideoAiInstructions(baseMessage, recordingId, useVideo),
|
|
96
107
|
};
|
|
97
108
|
|
|
98
109
|
await writeAppState(`clips-ai-request-${recordingId}`, request as any);
|
|
@@ -102,7 +113,7 @@ export async function queueTitleRegenerationRequest({
|
|
|
102
113
|
|
|
103
114
|
export default defineAction({
|
|
104
115
|
description:
|
|
105
|
-
"Regenerate this recording's title from its transcript using the configured cleanup/title path, falling back to a local transcript title when unavailable.",
|
|
116
|
+
"Regenerate this recording's title from its transcript using the configured cleanup/title path, falling back to a local transcript title when unavailable. When the user has enabled Include full video, delegates to the agent so it can watch the recording.",
|
|
106
117
|
schema: z.object({
|
|
107
118
|
recordingId: z.string().describe("Recording ID"),
|
|
108
119
|
transcriptText: z
|
|
@@ -137,6 +148,31 @@ export default defineAction({
|
|
|
137
148
|
args.transcriptText?.trim() ||
|
|
138
149
|
transcript?.fullText?.trim() ||
|
|
139
150
|
transcriptTextFromSegments(transcript?.segmentsJson);
|
|
151
|
+
|
|
152
|
+
const includeFullVideoInAi = await readIncludeFullVideoInAi();
|
|
153
|
+
|
|
154
|
+
// Full-video mode needs the agent to watch the clip; skip the transcript-
|
|
155
|
+
// only Gemini fast path so we don't generate titles from audio alone.
|
|
156
|
+
if (includeFullVideoInAi) {
|
|
157
|
+
await queueTitleRegenerationRequest({
|
|
158
|
+
recordingId: args.recordingId,
|
|
159
|
+
currentTitle: rec.title,
|
|
160
|
+
transcriptStatus: transcript?.status ?? "pending",
|
|
161
|
+
transcriptText: transcriptText || "",
|
|
162
|
+
segmentsJson: transcript?.segmentsJson ?? "[]",
|
|
163
|
+
ownerEmail: getRequestUserEmail() ?? transcript?.ownerEmail,
|
|
164
|
+
includeFullVideoInAi: true,
|
|
165
|
+
});
|
|
166
|
+
console.log(
|
|
167
|
+
`Delegation queued: regenerate-title (full video) for ${args.recordingId}`,
|
|
168
|
+
);
|
|
169
|
+
return {
|
|
170
|
+
queued: true,
|
|
171
|
+
recordingId: args.recordingId,
|
|
172
|
+
includeFullVideoInAi: true,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
140
176
|
if (
|
|
141
177
|
(!args.transcriptText && transcript?.status !== "ready") ||
|
|
142
178
|
!transcriptText
|
|
@@ -279,6 +315,7 @@ export default defineAction({
|
|
|
279
315
|
transcriptText,
|
|
280
316
|
segmentsJson: transcript?.segmentsJson ?? "[]",
|
|
281
317
|
ownerEmail: getRequestUserEmail() ?? transcript?.ownerEmail,
|
|
318
|
+
includeFullVideoInAi: false,
|
|
282
319
|
});
|
|
283
320
|
|
|
284
321
|
console.log(`Delegation queued: regenerate-title for ${args.recordingId}`);
|