@agent-native/core 0.90.3 → 0.90.5

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 (256) hide show
  1. package/bin/agent-native.js +25 -3
  2. package/corpus/README.md +1 -1
  3. package/corpus/core/CHANGELOG.md +17 -0
  4. package/corpus/core/bin/agent-native.js +25 -3
  5. package/corpus/core/package.json +1 -1
  6. package/corpus/core/src/agent/durable-background.ts +18 -18
  7. package/corpus/core/src/agent/engine/ai-sdk-engine.ts +8 -2
  8. package/corpus/core/src/agent/engine/anthropic-engine.ts +11 -1
  9. package/corpus/core/src/agent/engine/index.ts +1 -0
  10. package/corpus/core/src/agent/engine/registry.ts +63 -2
  11. package/corpus/core/src/agent/production-agent.ts +22 -11
  12. package/corpus/core/src/agent/run-manager.ts +17 -6
  13. package/corpus/core/src/agent/run-store.ts +16 -11
  14. package/corpus/core/src/cli/create.ts +35 -0
  15. package/corpus/core/src/cli/design-connect.ts +263 -1
  16. package/corpus/core/src/cli/index.ts +84 -7
  17. package/corpus/core/src/cli/workspacify.ts +34 -0
  18. package/corpus/core/src/client/KeepTabOpenNotice.tsx +20 -15
  19. package/corpus/core/src/client/RunStuckBanner.tsx +14 -13
  20. package/corpus/core/src/client/agent-chat-adapter.ts +28 -17
  21. package/corpus/core/src/client/history/VersionHistoryPanel.tsx +77 -47
  22. package/corpus/core/src/client/history/index.ts +3 -0
  23. package/corpus/core/src/client/history/use-history.ts +28 -0
  24. package/corpus/core/src/client/index.ts +8 -0
  25. package/corpus/core/src/client/review/index.ts +5 -0
  26. package/corpus/core/src/client/review/use-review.ts +40 -2
  27. package/corpus/core/src/client/use-run-stuck-detection.ts +8 -5
  28. package/corpus/core/src/history/actions/create-resource-version.ts +11 -8
  29. package/corpus/core/src/history/index.ts +0 -1
  30. package/corpus/core/src/history/registry.ts +24 -12
  31. package/corpus/core/src/history/store.ts +84 -53
  32. package/corpus/core/src/review/actions/consume-review-feedback.ts +15 -5
  33. package/corpus/core/src/review/actions/delete-review-comment.ts +15 -3
  34. package/corpus/core/src/review/actions/resolve-review-thread.ts +12 -5
  35. package/corpus/core/src/review/index.ts +0 -5
  36. package/corpus/core/src/review/registry.ts +24 -12
  37. package/corpus/core/src/review/store.ts +10 -7
  38. package/corpus/core/src/server/agent-chat-plugin.ts +6 -0
  39. package/corpus/core/src/server/credential-provider.ts +13 -3
  40. package/corpus/templates/assets/actions/_preset-skeleton-validation.ts +11 -11
  41. package/corpus/templates/assets/actions/generate-image.ts +64 -28
  42. package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +1 -1
  43. package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +91 -74
  44. package/corpus/templates/assets/server/lib/generation.ts +29 -4
  45. package/corpus/templates/assets/server/lib/image-processing.ts +131 -0
  46. package/corpus/templates/calendar/.agents/skills/event-management/SKILL.md +24 -2
  47. package/corpus/templates/calendar/AGENTS.md +3 -0
  48. package/corpus/templates/calendar/actions/create-event.ts +8 -34
  49. package/corpus/templates/calendar/actions/event-action-helpers.ts +52 -0
  50. package/corpus/templates/calendar/actions/manage-event-draft.ts +7 -34
  51. package/corpus/templates/calendar/actions/update-event.ts +10 -23
  52. package/corpus/templates/calendar/app/components/calendar/AttendeeAutocomplete.tsx +47 -0
  53. package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +23 -0
  54. package/corpus/templates/calendar/app/components/calendar/EventAttendeesSection.tsx +59 -2
  55. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +40 -1
  56. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +34 -1
  57. package/corpus/templates/calendar/app/hooks/use-events.ts +6 -0
  58. package/corpus/templates/calendar/app/i18n/zh-TW.ts +4 -0
  59. package/corpus/templates/calendar/app/i18n-data.ts +40 -0
  60. package/corpus/templates/calendar/changelog/2026-07-07-you-can-mark-event-guests-as-optional-while-inviting-them-or.md +6 -0
  61. package/corpus/templates/calendar/server/handlers/events.ts +1 -0
  62. package/corpus/templates/calendar/server/lib/google-calendar.ts +4 -0
  63. package/corpus/templates/calendar/server/plugins/agent-chat.ts +1 -1
  64. package/corpus/templates/calendar/shared/api.ts +2 -0
  65. package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +29 -3
  66. package/corpus/templates/clips/actions/generate-workflow.ts +19 -8
  67. package/corpus/templates/clips/actions/get-clips-ai-prefs.ts +36 -0
  68. package/corpus/templates/clips/actions/lib/clips-ai-prefs.ts +28 -0
  69. package/corpus/templates/clips/actions/regenerate-chapters.ts +21 -7
  70. package/corpus/templates/clips/actions/regenerate-summary.ts +26 -8
  71. package/corpus/templates/clips/actions/regenerate-title.ts +44 -7
  72. package/corpus/templates/clips/actions/update-clips-ai-prefs.ts +50 -0
  73. package/corpus/templates/clips/app/components/meetings/meeting-card.tsx +7 -2
  74. package/corpus/templates/clips/app/hooks/use-auto-title.ts +25 -10
  75. package/corpus/templates/clips/app/i18n/ar-SA.ts +28 -6
  76. package/corpus/templates/clips/app/i18n/de-DE.ts +28 -6
  77. package/corpus/templates/clips/app/i18n/en-US.ts +29 -6
  78. package/corpus/templates/clips/app/i18n/es-ES.ts +29 -6
  79. package/corpus/templates/clips/app/i18n/fr-FR.ts +30 -6
  80. package/corpus/templates/clips/app/i18n/hi-IN.ts +26 -6
  81. package/corpus/templates/clips/app/i18n/ja-JP.ts +27 -6
  82. package/corpus/templates/clips/app/i18n/ko-KR.ts +28 -6
  83. package/corpus/templates/clips/app/i18n/pt-BR.ts +28 -6
  84. package/corpus/templates/clips/app/i18n/zh-CN.ts +26 -6
  85. package/corpus/templates/clips/app/i18n/zh-TW.ts +25 -6
  86. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +73 -0
  87. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +1 -0
  88. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +70 -2
  89. package/corpus/templates/clips/changelog/2026-07-07-ai-tools-can-include-the-full-video-not-just-the-transcript-.md +6 -0
  90. package/corpus/templates/clips/changelog/2026-07-07-clips-desktop-now-surfaces-meetings-and-dictate-directly-in-.md +6 -0
  91. package/corpus/templates/clips/changelog/2026-07-07-meeting-notes-now-explain-exactly-how-to-start-granola-style.md +6 -0
  92. package/corpus/templates/clips/changelog/2026-07-07-meeting-start-alerts-now-include-separate-start-notes-and-jo.md +6 -0
  93. package/corpus/templates/clips/changelog/2026-07-07-recordings-start-more-predictably-and-newly-saved-clips-refr.md +6 -0
  94. package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
  95. package/corpus/templates/clips/desktop/src/app.tsx +435 -105
  96. package/corpus/templates/clips/desktop/src/lib/recorder.ts +27 -21
  97. package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +23 -22
  98. package/corpus/templates/clips/desktop/src/styles.css +167 -2
  99. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +1 -1
  100. package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +3 -7
  101. package/corpus/templates/clips/desktop/src-tauri/src/tray_meetings.rs +5 -4
  102. package/corpus/templates/clips/server/routes/_agent-native/clips/user-prefs.put.ts +16 -8
  103. package/corpus/templates/clips/shared/clips-ai-prefs.ts +81 -0
  104. package/corpus/templates/content/AGENTS.md +1 -0
  105. package/corpus/templates/content/actions/_database-source-utils.ts +73 -8
  106. package/corpus/templates/content/actions/_database-utils.ts +2 -1
  107. package/corpus/templates/content/actions/prepare-builder-source-review.ts +20 -1
  108. package/corpus/templates/content/actions/stage-builder-source-bulk-update.ts +663 -0
  109. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +33 -7
  110. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +53 -4
  111. package/corpus/templates/content/app/components/editor/database/settings.tsx +24 -0
  112. package/corpus/templates/content/app/hooks/use-content-database.ts +70 -1
  113. package/corpus/templates/content/app/hooks/use-document-properties.ts +63 -5
  114. package/corpus/templates/content/app/i18n/zh-TW.ts +3 -0
  115. package/corpus/templates/content/app/i18n-data.ts +31 -0
  116. package/corpus/templates/content/changelog/2026-07-01-builder-source-rows-can-be-staged-in-bulk-with-a-reviewable.md +6 -0
  117. package/corpus/templates/content/changelog/2026-07-07-builder-backed-database-fields-now-edit-like-normal-content-fields.md +6 -0
  118. package/corpus/templates/content/parity/matrix.md +24 -24
  119. package/corpus/templates/content/parity/matrix.ts +2 -0
  120. package/corpus/templates/content/shared/api.ts +59 -4
  121. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +16 -1
  122. package/corpus/templates/design/actions/add-localhost-screens.ts +1 -0
  123. package/corpus/templates/design/actions/connect-localhost.ts +26 -3
  124. package/corpus/templates/design/actions/open-visual-edit.ts +4 -37
  125. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +362 -12
  126. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +89 -14
  127. package/corpus/templates/design/app/components/design/bridge-security.ts +7 -1
  128. package/corpus/templates/design/app/components/design/multi-screen/types.ts +1 -1
  129. package/corpus/templates/design/app/i18n/zh-TW.ts +3 -0
  130. package/corpus/templates/design/app/i18n-data.ts +41 -0
  131. package/corpus/templates/design/changelog/2026-07-07-local-visual-edit-keeps-bridge-access-when-opening-previousl.md +6 -0
  132. package/corpus/templates/design/changelog/2026-07-07-local-visual-edit-now-keeps-the-live-app-connection-authenti.md +6 -0
  133. package/corpus/templates/design/changelog/2026-07-07-local-visual-edit-uses-live-app-iframes-for-click-to-edit-pr.md +6 -0
  134. package/dist/agent/durable-background.d.ts +12 -12
  135. package/dist/agent/durable-background.js +18 -18
  136. package/dist/agent/durable-background.js.map +1 -1
  137. package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
  138. package/dist/agent/engine/ai-sdk-engine.js +8 -2
  139. package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
  140. package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
  141. package/dist/agent/engine/anthropic-engine.js +11 -1
  142. package/dist/agent/engine/anthropic-engine.js.map +1 -1
  143. package/dist/agent/engine/index.d.ts +1 -1
  144. package/dist/agent/engine/index.d.ts.map +1 -1
  145. package/dist/agent/engine/index.js +1 -1
  146. package/dist/agent/engine/index.js.map +1 -1
  147. package/dist/agent/engine/registry.d.ts +14 -0
  148. package/dist/agent/engine/registry.d.ts.map +1 -1
  149. package/dist/agent/engine/registry.js +56 -2
  150. package/dist/agent/engine/registry.js.map +1 -1
  151. package/dist/agent/production-agent.d.ts +2 -2
  152. package/dist/agent/production-agent.d.ts.map +1 -1
  153. package/dist/agent/production-agent.js +18 -11
  154. package/dist/agent/production-agent.js.map +1 -1
  155. package/dist/agent/run-manager.d.ts +7 -1
  156. package/dist/agent/run-manager.d.ts.map +1 -1
  157. package/dist/agent/run-manager.js +6 -1
  158. package/dist/agent/run-manager.js.map +1 -1
  159. package/dist/agent/run-store.d.ts +1 -1
  160. package/dist/agent/run-store.d.ts.map +1 -1
  161. package/dist/agent/run-store.js +15 -10
  162. package/dist/agent/run-store.js.map +1 -1
  163. package/dist/cli/create.d.ts.map +1 -1
  164. package/dist/cli/create.js +31 -0
  165. package/dist/cli/create.js.map +1 -1
  166. package/dist/cli/design-connect.d.ts.map +1 -1
  167. package/dist/cli/design-connect.js +197 -1
  168. package/dist/cli/design-connect.js.map +1 -1
  169. package/dist/cli/index.js +76 -9
  170. package/dist/cli/index.js.map +1 -1
  171. package/dist/cli/workspacify.d.ts.map +1 -1
  172. package/dist/cli/workspacify.js +30 -0
  173. package/dist/cli/workspacify.js.map +1 -1
  174. package/dist/client/KeepTabOpenNotice.d.ts +9 -10
  175. package/dist/client/KeepTabOpenNotice.d.ts.map +1 -1
  176. package/dist/client/KeepTabOpenNotice.js +8 -4
  177. package/dist/client/KeepTabOpenNotice.js.map +1 -1
  178. package/dist/client/RunStuckBanner.d.ts.map +1 -1
  179. package/dist/client/RunStuckBanner.js +14 -13
  180. package/dist/client/RunStuckBanner.js.map +1 -1
  181. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  182. package/dist/client/agent-chat-adapter.js +25 -17
  183. package/dist/client/agent-chat-adapter.js.map +1 -1
  184. package/dist/client/history/VersionHistoryPanel.d.ts +1 -1
  185. package/dist/client/history/VersionHistoryPanel.d.ts.map +1 -1
  186. package/dist/client/history/VersionHistoryPanel.js +12 -5
  187. package/dist/client/history/VersionHistoryPanel.js.map +1 -1
  188. package/dist/client/history/index.d.ts +1 -1
  189. package/dist/client/history/index.d.ts.map +1 -1
  190. package/dist/client/history/index.js +1 -1
  191. package/dist/client/history/index.js.map +1 -1
  192. package/dist/client/history/use-history.d.ts +12 -0
  193. package/dist/client/history/use-history.d.ts.map +1 -1
  194. package/dist/client/history/use-history.js +6 -0
  195. package/dist/client/history/use-history.js.map +1 -1
  196. package/dist/client/index.d.ts +2 -2
  197. package/dist/client/index.d.ts.map +1 -1
  198. package/dist/client/index.js +2 -2
  199. package/dist/client/index.js.map +1 -1
  200. package/dist/client/review/index.d.ts +1 -1
  201. package/dist/client/review/index.d.ts.map +1 -1
  202. package/dist/client/review/index.js +1 -1
  203. package/dist/client/review/index.js.map +1 -1
  204. package/dist/client/review/use-review.d.ts +23 -0
  205. package/dist/client/review/use-review.d.ts.map +1 -1
  206. package/dist/client/review/use-review.js +8 -0
  207. package/dist/client/review/use-review.js.map +1 -1
  208. package/dist/client/use-run-stuck-detection.d.ts +1 -1
  209. package/dist/client/use-run-stuck-detection.d.ts.map +1 -1
  210. package/dist/client/use-run-stuck-detection.js +6 -4
  211. package/dist/client/use-run-stuck-detection.js.map +1 -1
  212. package/dist/collab/struct-routes.d.ts +1 -1
  213. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  214. package/dist/history/actions/create-resource-version.js +7 -4
  215. package/dist/history/actions/create-resource-version.js.map +1 -1
  216. package/dist/history/index.d.ts +1 -1
  217. package/dist/history/index.d.ts.map +1 -1
  218. package/dist/history/index.js +1 -1
  219. package/dist/history/index.js.map +1 -1
  220. package/dist/history/registry.d.ts.map +1 -1
  221. package/dist/history/registry.js +14 -12
  222. package/dist/history/registry.js.map +1 -1
  223. package/dist/history/store.d.ts.map +1 -1
  224. package/dist/history/store.js +74 -49
  225. package/dist/history/store.js.map +1 -1
  226. package/dist/notifications/routes.d.ts +1 -1
  227. package/dist/resources/handlers.d.ts +3 -3
  228. package/dist/review/actions/consume-review-feedback.d.ts +1 -0
  229. package/dist/review/actions/consume-review-feedback.js +8 -2
  230. package/dist/review/actions/consume-review-feedback.js.map +1 -1
  231. package/dist/review/actions/delete-review-comment.d.ts +2 -1
  232. package/dist/review/actions/delete-review-comment.js +11 -3
  233. package/dist/review/actions/delete-review-comment.js.map +1 -1
  234. package/dist/review/actions/resolve-review-thread.d.ts +2 -1
  235. package/dist/review/actions/resolve-review-thread.js +5 -2
  236. package/dist/review/actions/resolve-review-thread.js.map +1 -1
  237. package/dist/review/index.d.ts +1 -1
  238. package/dist/review/index.d.ts.map +1 -1
  239. package/dist/review/index.js +1 -1
  240. package/dist/review/index.js.map +1 -1
  241. package/dist/review/registry.d.ts.map +1 -1
  242. package/dist/review/registry.js +14 -12
  243. package/dist/review/registry.js.map +1 -1
  244. package/dist/review/store.d.ts +3 -3
  245. package/dist/review/store.d.ts.map +1 -1
  246. package/dist/review/store.js +7 -4
  247. package/dist/review/store.js.map +1 -1
  248. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  249. package/dist/server/agent-chat-plugin.js +5 -0
  250. package/dist/server/agent-chat-plugin.js.map +1 -1
  251. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  252. package/dist/server/credential-provider.d.ts +2 -0
  253. package/dist/server/credential-provider.d.ts.map +1 -1
  254. package/dist/server/credential-provider.js +13 -3
  255. package/dist/server/credential-provider.js.map +1 -1
  256. 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: "جارٍ البحث عن أشخاص",
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: added
3
+ date: 2026-07-07
4
+ ---
5
+
6
+ You can mark event guests as optional while inviting them or later from the guest list
@@ -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
- | 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 |
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" | `generate-ai-metadata --id=<id> --kind=summary` → agent writes `update-recording --description=...` |
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
- message:
99
- `Generate a ${args.kind.toUpperCase()} workflow document from recording ${args.recordingId} ` +
100
- `(title: "${rec.title}"). Read the transcript from this request's context. ` +
101
- `${KIND_PROMPTS[args.kind]} ` +
102
- `Then write the final markdown to application_state key "${stateKey}" as ` +
103
- `\`{ kind: "${args.kind}", status: "ready", content: "...", recordingId: "${args.recordingId}" }\`. ` +
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
- message:
51
- `Generate chapters for recording ${args.recordingId} (duration ${rec.durationMs}ms). ` +
52
- `Read the transcript segments in this request's context, identify topic transitions, ` +
53
- `and call \`set-chapters --recordingId=${args.recordingId} --chapters='[{ "startMs": 0, "title": "Intro" }, ...]'\`. ` +
54
- `Aim for 3–8 chapters. Each chapter title should be 3–6 words and capture the essence of that section.`,
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 { queued: true, recordingId: args.recordingId };
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
- if (transcript?.status !== "ready" || !transcript.fullText?.trim()) {
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
- message:
64
- `Regenerate the description for recording ${args.recordingId}. ` +
65
- `Read the transcript in this request's context and call ` +
66
- `\`update-recording --id=${args.recordingId} --description="..."\` with a 2–4 ` +
67
- `sentence summary of what the recording covers. Title: "${rec.title}".`,
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 { queued: true, recordingId: args.recordingId };
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
- message:
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.",
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}`);