@agent-native/core 0.90.2 → 0.90.3
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +12 -0
- package/corpus/core/docs/content/agent-native-toolkit.mdx +87 -80
- package/corpus/core/docs/content/locales/ar-SA/agent-native-toolkit.mdx +89 -80
- package/corpus/core/docs/content/locales/de-DE/agent-native-toolkit.mdx +89 -80
- package/corpus/core/docs/content/locales/es-ES/agent-native-toolkit.mdx +89 -80
- package/corpus/core/docs/content/locales/fr-FR/agent-native-toolkit.mdx +89 -80
- package/corpus/core/docs/content/locales/hi-IN/agent-native-toolkit.mdx +89 -80
- package/corpus/core/docs/content/locales/ja-JP/agent-native-toolkit.mdx +89 -80
- package/corpus/core/docs/content/locales/ko-KR/agent-native-toolkit.mdx +89 -80
- package/corpus/core/docs/content/locales/pt-BR/agent-native-toolkit.mdx +89 -80
- package/corpus/core/docs/content/locales/zh-CN/agent-native-toolkit.mdx +89 -80
- package/corpus/core/docs/content/locales/zh-TW/agent-native-toolkit.mdx +89 -80
- package/corpus/core/docs/content/toolkit-agent-ux.mdx +43 -0
- package/corpus/core/docs/content/toolkit-app-adapters.mdx +9 -0
- package/corpus/core/docs/content/toolkit-collaboration-ui.mdx +12 -0
- package/corpus/core/docs/content/toolkit-collaboration.mdx +74 -0
- package/corpus/core/docs/content/toolkit-command-navigation.mdx +106 -0
- package/corpus/core/docs/content/toolkit-comments-review.mdx +98 -0
- package/corpus/core/docs/content/toolkit-history.mdx +95 -0
- package/corpus/core/docs/content/toolkit-observability.mdx +41 -0
- package/corpus/core/docs/content/toolkit-org-team.mdx +80 -0
- package/corpus/core/docs/content/toolkit-resources.mdx +57 -0
- package/corpus/core/docs/content/toolkit-settings.mdx +65 -0
- package/corpus/core/docs/content/toolkit-setup-connections.mdx +109 -0
- package/corpus/core/docs/content/toolkit-sharing-ui.mdx +18 -6
- package/corpus/core/docs/content/toolkit-sharing.mdx +81 -0
- package/corpus/core/docs/content/toolkit-shell-hooks.mdx +9 -0
- package/corpus/core/docs/content/toolkit-ui.mdx +9 -0
- package/corpus/core/package.json +35 -1
- package/corpus/core/src/agent/engine/ai-sdk-engine.ts +19 -1
- package/corpus/core/src/agent/engine/anthropic-engine.ts +25 -1
- package/corpus/core/src/agent/engine/registry.ts +23 -16
- package/corpus/core/src/agent/production-agent.ts +37 -6
- package/corpus/core/src/client/command-navigation/index.ts +15 -0
- package/corpus/core/src/client/comments-review/index.ts +1 -0
- package/corpus/core/src/client/history/VersionHistoryPanel.tsx +145 -0
- package/corpus/core/src/client/history/index.ts +18 -0
- package/corpus/core/src/client/history/use-history.ts +86 -0
- package/corpus/core/src/client/index.ts +76 -9
- package/corpus/core/src/client/org/OrgSwitcher.tsx +6 -6
- package/corpus/core/src/client/org/RequireActiveOrg.tsx +2 -2
- package/corpus/core/src/client/org/TeamPage.tsx +3 -3
- package/corpus/core/src/client/org/hooks.ts +32 -0
- package/corpus/core/src/client/org/index.ts +30 -1
- package/corpus/core/src/client/org-team/index.ts +1 -0
- package/corpus/core/src/client/review/ReviewStatusBadge.tsx +39 -0
- package/corpus/core/src/client/review/ReviewThreadPanel.tsx +278 -0
- package/corpus/core/src/client/review/index.ts +25 -0
- package/corpus/core/src/client/review/use-review.ts +114 -0
- package/corpus/core/src/client/settings/index.ts +11 -1
- package/corpus/core/src/client/setup-connections/BuilderConnectCard.tsx +94 -0
- package/corpus/core/src/client/setup-connections/ProviderReadinessBadge.tsx +73 -0
- package/corpus/core/src/client/setup-connections/SetupConnectionsPage.tsx +94 -0
- package/corpus/core/src/client/setup-connections/index.ts +46 -0
- package/corpus/core/src/client/sharing/ShareButton.tsx +20 -14
- package/corpus/core/src/client/sharing/ShareDialog.tsx +3 -3
- package/corpus/core/src/command-navigation/actions.ts +100 -0
- package/corpus/core/src/command-navigation/index.ts +12 -0
- package/corpus/core/src/comments-review/index.ts +1 -0
- package/corpus/core/src/file-upload/builder.ts +24 -3
- package/corpus/core/src/file-upload/types.ts +3 -1
- package/corpus/core/src/history/actions/create-resource-version.ts +89 -0
- package/corpus/core/src/history/actions/get-resource-version.ts +60 -0
- package/corpus/core/src/history/actions/list-resource-history.ts +53 -0
- package/corpus/core/src/history/actions/list-resource-versions.ts +43 -0
- package/corpus/core/src/history/actions/restore-resource-version.ts +96 -0
- package/corpus/core/src/history/index.ts +27 -0
- package/corpus/core/src/history/registry.ts +99 -0
- package/corpus/core/src/history/store.ts +348 -0
- package/corpus/core/src/history/types.ts +69 -0
- package/corpus/core/src/index.ts +10 -0
- package/corpus/core/src/navigation/index.ts +170 -0
- package/corpus/core/src/org/index.ts +8 -0
- package/corpus/core/src/org/permissions.ts +30 -0
- package/corpus/core/src/org-team/index.ts +1 -0
- package/corpus/core/src/private-blob/registry.ts +1 -0
- package/corpus/core/src/review/actions/consume-review-feedback.ts +38 -0
- package/corpus/core/src/review/actions/create-review-comment.ts +107 -0
- package/corpus/core/src/review/actions/delete-review-comment.ts +55 -0
- package/corpus/core/src/review/actions/get-review-feedback.ts +54 -0
- package/corpus/core/src/review/actions/list-review-comments.ts +53 -0
- package/corpus/core/src/review/actions/reply-review-comment.ts +107 -0
- package/corpus/core/src/review/actions/resolve-review-thread.ts +60 -0
- package/corpus/core/src/review/actions/set-review-status.ts +58 -0
- package/corpus/core/src/review/index.ts +36 -0
- package/corpus/core/src/review/mentions.ts +44 -0
- package/corpus/core/src/review/registry.ts +99 -0
- package/corpus/core/src/review/store.ts +687 -0
- package/corpus/core/src/review/types.ts +97 -0
- package/corpus/core/src/server/action-discovery.ts +54 -0
- package/corpus/core/src/server/agent-engine-api-key-route.ts +5 -0
- package/corpus/core/src/server/credential-provider.ts +108 -0
- package/corpus/core/src/setup-connections/index.ts +89 -0
- package/corpus/core/src/setup-connections/onboarding.ts +47 -0
- package/corpus/core/src/transcription/builder-transcription.ts +9 -2
- package/corpus/core/src/vite/action-types-plugin.ts +52 -0
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +2 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +2 -2
- package/corpus/templates/analytics/app/global.css +22 -10
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +6 -1
- package/corpus/templates/analytics/app/i18n-data.ts +81 -13
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +2 -2
- package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +2 -2
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +528 -108
- package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +466 -183
- package/corpus/templates/analytics/changelog/2026-07-07-session-replays-load-sooner-show-clearer-activity-timelines-.md +6 -0
- package/corpus/templates/brain/app/routes/settings.tsx +2 -2
- package/corpus/templates/calendar/app/components/calendar/AttendeeAutocomplete.tsx +32 -6
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +120 -40
- package/corpus/templates/calendar/app/hooks/use-people.ts +55 -0
- package/corpus/templates/calendar/changelog/2026-07-07-guest-suggestions-now-find-coworkers-from-your-google-worksp.md +6 -0
- package/corpus/templates/calendar/changelog/2026-07-07-zoom-stays-selected-after-connecting-it-from-a-draft-event.md +6 -0
- package/corpus/templates/clips/actions/create-recording.ts +5 -1
- package/corpus/templates/clips/actions/finalize-recording.ts +140 -1
- package/corpus/templates/clips/actions/import-loom-recording.ts +1 -0
- package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +1 -0
- package/corpus/templates/clips/actions/request-transcript.ts +31 -0
- package/corpus/templates/clips/actions/set-thumbnail.ts +2 -0
- package/corpus/templates/clips/app/components/library/organization-switcher.tsx +2 -2
- package/corpus/templates/clips/app/components/player/scrubber-position.ts +9 -0
- package/corpus/templates/clips/app/components/player/scrubber.tsx +5 -2
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +69 -41
- package/corpus/templates/clips/app/components/player/video-player.tsx +38 -1
- package/corpus/templates/clips/app/components/sharing/share-ui.tsx +3 -3
- package/corpus/templates/clips/app/components/sharing/slack-share-hint.tsx +9 -19
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +9 -3
- package/corpus/templates/clips/app/routes/record.tsx +21 -12
- package/corpus/templates/clips/changelog/2026-07-02-recordings-now-wait-for-storage-media-to-serve-before-finishing.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-07-a-pending-app-update-no-longer-blocks-screen-recording-updat.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-07-chrome-extension-recordings-keep-audio-after-refreshing-tab.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-07-clip-playback-progress-now-starts-and-finishes-at-the-right-times.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-07-sharing-public-clips-now-stays-focused-on-the-normal-link-wi.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/background.ts +18 -0
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +23 -8
- package/corpus/templates/clips/desktop/src/app.tsx +40 -3
- package/corpus/templates/clips/desktop/src/hooks/useMediaDevices.ts +19 -7
- package/corpus/templates/clips/desktop/src/lib/permissions.ts +2 -0
- package/corpus/templates/clips/desktop/src/lib/updater.ts +25 -2
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +7 -0
- package/corpus/templates/clips/server/routes/api/recordings/[recordingId]/thumbnail.post.ts +1 -0
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +22 -5
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +8 -0
- package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +13 -6
- package/corpus/templates/clips/shared/finalize-recovery.ts +12 -0
- package/corpus/templates/content/actions/delete-document.ts +337 -52
- package/corpus/templates/content/changelog/2026-07-07-permanently-deleting-trashed-databases-now-finishes-reliably.md +6 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +2 -2
- package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.js +15 -1
- package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
- package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
- package/dist/agent/engine/anthropic-engine.js +20 -1
- package/dist/agent/engine/anthropic-engine.js.map +1 -1
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js +22 -14
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +27 -7
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/client/command-navigation/index.d.ts +4 -0
- package/dist/client/command-navigation/index.d.ts.map +1 -0
- package/dist/client/command-navigation/index.js +4 -0
- package/dist/client/command-navigation/index.js.map +1 -0
- package/dist/client/comments-review/index.d.ts +2 -0
- package/dist/client/comments-review/index.d.ts.map +1 -0
- package/dist/client/comments-review/index.js +2 -0
- package/dist/client/comments-review/index.js.map +1 -0
- package/dist/client/history/VersionHistoryPanel.d.ts +18 -0
- package/dist/client/history/VersionHistoryPanel.d.ts.map +1 -0
- package/dist/client/history/VersionHistoryPanel.js +24 -0
- package/dist/client/history/VersionHistoryPanel.js.map +1 -0
- package/dist/client/history/index.d.ts +3 -0
- package/dist/client/history/index.d.ts.map +1 -0
- package/dist/client/history/index.js +3 -0
- package/dist/client/history/index.js.map +1 -0
- package/dist/client/history/use-history.d.ts +46 -0
- package/dist/client/history/use-history.d.ts.map +1 -0
- package/dist/client/history/use-history.js +18 -0
- package/dist/client/history/use-history.js.map +1 -0
- package/dist/client/index.d.ts +6 -4
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +6 -4
- package/dist/client/index.js.map +1 -1
- package/dist/client/org/OrgSwitcher.js +5 -5
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/org/RequireActiveOrg.js +2 -2
- package/dist/client/org/RequireActiveOrg.js.map +1 -1
- package/dist/client/org/TeamPage.js +3 -3
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/org/hooks.d.ts +12 -1
- package/dist/client/org/hooks.d.ts.map +1 -1
- package/dist/client/org/hooks.js +15 -0
- package/dist/client/org/hooks.js.map +1 -1
- package/dist/client/org/index.d.ts +4 -2
- package/dist/client/org/index.d.ts.map +1 -1
- package/dist/client/org/index.js +3 -1
- package/dist/client/org/index.js.map +1 -1
- package/dist/client/org-team/index.d.ts +2 -0
- package/dist/client/org-team/index.d.ts.map +1 -0
- package/dist/client/org-team/index.js +2 -0
- package/dist/client/org-team/index.js.map +1 -0
- package/dist/client/review/ReviewStatusBadge.d.ts +7 -0
- package/dist/client/review/ReviewStatusBadge.d.ts.map +1 -0
- package/dist/client/review/ReviewStatusBadge.js +19 -0
- package/dist/client/review/ReviewStatusBadge.js.map +1 -0
- package/dist/client/review/ReviewThreadPanel.d.ts +20 -0
- package/dist/client/review/ReviewThreadPanel.d.ts.map +1 -0
- package/dist/client/review/ReviewThreadPanel.js +84 -0
- package/dist/client/review/ReviewThreadPanel.js.map +1 -0
- package/dist/client/review/index.d.ts +4 -0
- package/dist/client/review/index.d.ts.map +1 -0
- package/dist/client/review/index.js +4 -0
- package/dist/client/review/index.js.map +1 -0
- package/dist/client/review/use-review.d.ts +68 -0
- package/dist/client/review/use-review.d.ts.map +1 -0
- package/dist/client/review/use-review.js +22 -0
- package/dist/client/review/use-review.js.map +1 -0
- package/dist/client/settings/index.d.ts +1 -1
- package/dist/client/settings/index.d.ts.map +1 -1
- package/dist/client/settings/index.js +1 -1
- package/dist/client/settings/index.js.map +1 -1
- package/dist/client/setup-connections/BuilderConnectCard.d.ts +9 -0
- package/dist/client/setup-connections/BuilderConnectCard.d.ts.map +1 -0
- package/dist/client/setup-connections/BuilderConnectCard.js +25 -0
- package/dist/client/setup-connections/BuilderConnectCard.js.map +1 -0
- package/dist/client/setup-connections/ProviderReadinessBadge.d.ts +8 -0
- package/dist/client/setup-connections/ProviderReadinessBadge.d.ts.map +1 -0
- package/dist/client/setup-connections/ProviderReadinessBadge.js +32 -0
- package/dist/client/setup-connections/ProviderReadinessBadge.js.map +1 -0
- package/dist/client/setup-connections/SetupConnectionsPage.d.ts +17 -0
- package/dist/client/setup-connections/SetupConnectionsPage.d.ts.map +1 -0
- package/dist/client/setup-connections/SetupConnectionsPage.js +10 -0
- package/dist/client/setup-connections/SetupConnectionsPage.js.map +1 -0
- package/dist/client/setup-connections/index.d.ts +7 -0
- package/dist/client/setup-connections/index.d.ts.map +1 -0
- package/dist/client/setup-connections/index.js +7 -0
- package/dist/client/setup-connections/index.js.map +1 -0
- package/dist/client/sharing/ShareButton.d.ts +4 -4
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +13 -7
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/sharing/ShareDialog.js +3 -3
- package/dist/client/sharing/ShareDialog.js.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/command-navigation/actions.d.ts +25 -0
- package/dist/command-navigation/actions.d.ts.map +1 -0
- package/dist/command-navigation/actions.js +64 -0
- package/dist/command-navigation/actions.js.map +1 -0
- package/dist/command-navigation/index.d.ts +4 -0
- package/dist/command-navigation/index.d.ts.map +1 -0
- package/dist/command-navigation/index.js +4 -0
- package/dist/command-navigation/index.js.map +1 -0
- package/dist/comments-review/index.d.ts +2 -0
- package/dist/comments-review/index.d.ts.map +1 -0
- package/dist/comments-review/index.js +2 -0
- package/dist/comments-review/index.js.map +1 -0
- package/dist/file-upload/builder.d.ts.map +1 -1
- package/dist/file-upload/builder.js +18 -2
- package/dist/file-upload/builder.js.map +1 -1
- package/dist/file-upload/types.d.ts +3 -0
- package/dist/file-upload/types.d.ts.map +1 -1
- package/dist/file-upload/types.js.map +1 -1
- package/dist/history/actions/create-resource-version.d.ts +10 -0
- package/dist/history/actions/create-resource-version.d.ts.map +1 -0
- package/dist/history/actions/create-resource-version.js +65 -0
- package/dist/history/actions/create-resource-version.js.map +1 -0
- package/dist/history/actions/get-resource-version.d.ts +10 -0
- package/dist/history/actions/get-resource-version.d.ts.map +1 -0
- package/dist/history/actions/get-resource-version.js +38 -0
- package/dist/history/actions/get-resource-version.js.map +1 -0
- package/dist/history/actions/list-resource-history.d.ts +10 -0
- package/dist/history/actions/list-resource-history.d.ts.map +1 -0
- package/dist/history/actions/list-resource-history.js +45 -0
- package/dist/history/actions/list-resource-history.js.map +1 -0
- package/dist/history/actions/list-resource-versions.d.ts +10 -0
- package/dist/history/actions/list-resource-versions.d.ts.map +1 -0
- package/dist/history/actions/list-resource-versions.js +35 -0
- package/dist/history/actions/list-resource-versions.js.map +1 -0
- package/dist/history/actions/restore-resource-version.d.ts +11 -0
- package/dist/history/actions/restore-resource-version.d.ts.map +1 -0
- package/dist/history/actions/restore-resource-version.js +59 -0
- package/dist/history/actions/restore-resource-version.js.map +1 -0
- package/dist/history/index.d.ts +4 -0
- package/dist/history/index.d.ts.map +1 -0
- package/dist/history/index.js +3 -0
- package/dist/history/index.js.map +1 -0
- package/dist/history/registry.d.ts +10 -0
- package/dist/history/registry.d.ts.map +1 -0
- package/dist/history/registry.js +61 -0
- package/dist/history/registry.js.map +1 -0
- package/dist/history/store.d.ts +34 -0
- package/dist/history/store.d.ts.map +1 -0
- package/dist/history/store.js +265 -0
- package/dist/history/store.js.map +1 -0
- package/dist/history/types.d.ts +55 -0
- package/dist/history/types.d.ts.map +1 -0
- package/dist/history/types.js +2 -0
- package/dist/history/types.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/navigation/index.d.ts +53 -0
- package/dist/navigation/index.d.ts.map +1 -0
- package/dist/navigation/index.js +105 -0
- package/dist/navigation/index.js.map +1 -0
- package/dist/org/index.d.ts +1 -0
- package/dist/org/index.d.ts.map +1 -1
- package/dist/org/index.js +1 -0
- package/dist/org/index.js.map +1 -1
- package/dist/org/permissions.d.ts +7 -0
- package/dist/org/permissions.d.ts.map +1 -0
- package/dist/org/permissions.js +21 -0
- package/dist/org/permissions.js.map +1 -0
- package/dist/org-team/index.d.ts +2 -0
- package/dist/org-team/index.d.ts.map +1 -0
- package/dist/org-team/index.js +2 -0
- package/dist/org-team/index.js.map +1 -0
- package/dist/private-blob/registry.d.ts.map +1 -1
- package/dist/private-blob/registry.js +1 -0
- package/dist/private-blob/registry.js.map +1 -1
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/review/actions/consume-review-feedback.d.ts +9 -0
- package/dist/review/actions/consume-review-feedback.d.ts.map +1 -0
- package/dist/review/actions/consume-review-feedback.js +29 -0
- package/dist/review/actions/consume-review-feedback.js.map +1 -0
- package/dist/review/actions/create-review-comment.d.ts +18 -0
- package/dist/review/actions/create-review-comment.d.ts.map +1 -0
- package/dist/review/actions/create-review-comment.js +81 -0
- package/dist/review/actions/create-review-comment.js.map +1 -0
- package/dist/review/actions/delete-review-comment.d.ts +10 -0
- package/dist/review/actions/delete-review-comment.d.ts.map +1 -0
- package/dist/review/actions/delete-review-comment.js +45 -0
- package/dist/review/actions/delete-review-comment.js.map +1 -0
- package/dist/review/actions/get-review-feedback.d.ts +10 -0
- package/dist/review/actions/get-review-feedback.d.ts.map +1 -0
- package/dist/review/actions/get-review-feedback.js +45 -0
- package/dist/review/actions/get-review-feedback.js.map +1 -0
- package/dist/review/actions/list-review-comments.d.ts +13 -0
- package/dist/review/actions/list-review-comments.d.ts.map +1 -0
- package/dist/review/actions/list-review-comments.js +44 -0
- package/dist/review/actions/list-review-comments.js.map +1 -0
- package/dist/review/actions/reply-review-comment.d.ts +16 -0
- package/dist/review/actions/reply-review-comment.d.ts.map +1 -0
- package/dist/review/actions/reply-review-comment.js +84 -0
- package/dist/review/actions/reply-review-comment.js.map +1 -0
- package/dist/review/actions/resolve-review-thread.d.ts +11 -0
- package/dist/review/actions/resolve-review-thread.d.ts.map +1 -0
- package/dist/review/actions/resolve-review-thread.js +46 -0
- package/dist/review/actions/resolve-review-thread.js.map +1 -0
- package/dist/review/actions/set-review-status.d.ts +9 -0
- package/dist/review/actions/set-review-status.d.ts.map +1 -0
- package/dist/review/actions/set-review-status.js +43 -0
- package/dist/review/actions/set-review-status.js.map +1 -0
- package/dist/review/index.d.ts +5 -0
- package/dist/review/index.d.ts.map +1 -0
- package/dist/review/index.js +4 -0
- package/dist/review/index.js.map +1 -0
- package/dist/review/mentions.d.ts +4 -0
- package/dist/review/mentions.d.ts.map +1 -0
- package/dist/review/mentions.js +39 -0
- package/dist/review/mentions.js.map +1 -0
- package/dist/review/registry.d.ts +10 -0
- package/dist/review/registry.d.ts.map +1 -0
- package/dist/review/registry.js +61 -0
- package/dist/review/registry.js.map +1 -0
- package/dist/review/store.d.ts +63 -0
- package/dist/review/store.d.ts.map +1 -0
- package/dist/review/store.js +558 -0
- package/dist/review/store.js.map +1 -0
- package/dist/review/types.d.ts +77 -0
- package/dist/review/types.d.ts.map +1 -0
- package/dist/review/types.js +2 -0
- package/dist/review/types.js.map +1 -0
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +54 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts.map +1 -1
- package/dist/server/agent-engine-api-key-route.js +5 -0
- package/dist/server/agent-engine-api-key-route.js.map +1 -1
- package/dist/server/credential-provider.d.ts +26 -0
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +82 -0
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/setup-connections/index.d.ts +6 -0
- package/dist/setup-connections/index.d.ts.map +1 -0
- package/dist/setup-connections/index.js +6 -0
- package/dist/setup-connections/index.js.map +1 -0
- package/dist/setup-connections/onboarding.d.ts +14 -0
- package/dist/setup-connections/onboarding.d.ts.map +1 -0
- package/dist/setup-connections/onboarding.js +23 -0
- package/dist/setup-connections/onboarding.js.map +1 -0
- package/dist/transcription/builder-transcription.d.ts +1 -0
- package/dist/transcription/builder-transcription.d.ts.map +1 -1
- package/dist/transcription/builder-transcription.js +5 -2
- package/dist/transcription/builder-transcription.js.map +1 -1
- package/dist/vite/action-types-plugin.d.ts.map +1 -1
- package/dist/vite/action-types-plugin.js +52 -0
- package/dist/vite/action-types-plugin.js.map +1 -1
- package/docs/content/agent-native-toolkit.mdx +87 -80
- package/docs/content/locales/ar-SA/agent-native-toolkit.mdx +89 -80
- package/docs/content/locales/de-DE/agent-native-toolkit.mdx +89 -80
- package/docs/content/locales/es-ES/agent-native-toolkit.mdx +89 -80
- package/docs/content/locales/fr-FR/agent-native-toolkit.mdx +89 -80
- package/docs/content/locales/hi-IN/agent-native-toolkit.mdx +89 -80
- package/docs/content/locales/ja-JP/agent-native-toolkit.mdx +89 -80
- package/docs/content/locales/ko-KR/agent-native-toolkit.mdx +89 -80
- package/docs/content/locales/pt-BR/agent-native-toolkit.mdx +89 -80
- package/docs/content/locales/zh-CN/agent-native-toolkit.mdx +89 -80
- package/docs/content/locales/zh-TW/agent-native-toolkit.mdx +89 -80
- package/docs/content/toolkit-agent-ux.mdx +43 -0
- package/docs/content/toolkit-app-adapters.mdx +9 -0
- package/docs/content/toolkit-collaboration-ui.mdx +12 -0
- package/docs/content/toolkit-collaboration.mdx +74 -0
- package/docs/content/toolkit-command-navigation.mdx +106 -0
- package/docs/content/toolkit-comments-review.mdx +98 -0
- package/docs/content/toolkit-history.mdx +95 -0
- package/docs/content/toolkit-observability.mdx +41 -0
- package/docs/content/toolkit-org-team.mdx +80 -0
- package/docs/content/toolkit-resources.mdx +57 -0
- package/docs/content/toolkit-settings.mdx +65 -0
- package/docs/content/toolkit-setup-connections.mdx +109 -0
- package/docs/content/toolkit-sharing-ui.mdx +18 -6
- package/docs/content/toolkit-sharing.mdx +81 -0
- package/docs/content/toolkit-shell-hooks.mdx +9 -0
- package/docs/content/toolkit-ui.mdx +9 -0
- package/package.json +36 -2
|
@@ -10,12 +10,12 @@ import {
|
|
|
10
10
|
import { TeamPage } from "@agent-native/core/client/org";
|
|
11
11
|
import {
|
|
12
12
|
IconAdjustments,
|
|
13
|
-
IconBuilding,
|
|
14
13
|
IconDeviceFloppy,
|
|
15
14
|
IconFileText,
|
|
16
15
|
IconGauge,
|
|
17
16
|
IconMessageCircle,
|
|
18
17
|
IconShieldCheck,
|
|
18
|
+
IconUsersGroup,
|
|
19
19
|
} from "@tabler/icons-react";
|
|
20
20
|
import { useEffect, useMemo, useState } from "react";
|
|
21
21
|
|
|
@@ -152,7 +152,7 @@ export default function SettingsRoute() {
|
|
|
152
152
|
<Card>
|
|
153
153
|
<CardHeader>
|
|
154
154
|
<CardTitle className="flex items-center gap-2 text-base">
|
|
155
|
-
<
|
|
155
|
+
<IconUsersGroup className="size-4 text-primary" />
|
|
156
156
|
{t("settings.identityTitle")}
|
|
157
157
|
</CardTitle>
|
|
158
158
|
<CardDescription>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { useT } from "@agent-native/core/client";
|
|
2
2
|
import {
|
|
3
3
|
IconAddressBook,
|
|
4
|
-
IconBuilding,
|
|
5
4
|
IconLoader2,
|
|
6
5
|
IconUserCircle,
|
|
6
|
+
IconUsersGroup,
|
|
7
7
|
IconX,
|
|
8
8
|
} from "@tabler/icons-react";
|
|
9
9
|
import {
|
|
@@ -25,7 +25,9 @@ import {
|
|
|
25
25
|
} from "@/components/ui/popover";
|
|
26
26
|
import {
|
|
27
27
|
filterPeopleResults,
|
|
28
|
+
mergePeopleResults,
|
|
28
29
|
usePeopleContacts,
|
|
30
|
+
usePeopleSearch,
|
|
29
31
|
type PeopleSearchResult,
|
|
30
32
|
} from "@/hooks/use-people";
|
|
31
33
|
import { isMcpEmbedSurface } from "@/lib/mcp-embed";
|
|
@@ -87,7 +89,7 @@ function sourceLabel(
|
|
|
87
89
|
|
|
88
90
|
function SourceIcon({ source }: { source?: PeopleSearchResult["source"] }) {
|
|
89
91
|
if (source === "directory") {
|
|
90
|
-
return <
|
|
92
|
+
return <IconUsersGroup className="h-3 w-3" />;
|
|
91
93
|
}
|
|
92
94
|
return <IconAddressBook className="h-3 w-3" />;
|
|
93
95
|
}
|
|
@@ -129,10 +131,15 @@ export const AttendeeAutocomplete = forwardRef<
|
|
|
129
131
|
) {
|
|
130
132
|
const t = useT();
|
|
131
133
|
const [inputValue, setInputValue] = useState("");
|
|
134
|
+
const [searchQuery, setSearchQuery] = useState("");
|
|
132
135
|
const [open, setOpen] = useState(false);
|
|
133
136
|
const [activeIndex, setActiveIndex] = useState(0);
|
|
134
137
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
135
138
|
const contacts = usePeopleContacts();
|
|
139
|
+
const peopleSearch = usePeopleSearch(
|
|
140
|
+
searchQuery,
|
|
141
|
+
inputValue.trim().length > 0,
|
|
142
|
+
);
|
|
136
143
|
|
|
137
144
|
const selectedEmailSet = useMemo(
|
|
138
145
|
() =>
|
|
@@ -144,19 +151,38 @@ export const AttendeeAutocomplete = forwardRef<
|
|
|
144
151
|
[attendees, selectedEmails],
|
|
145
152
|
);
|
|
146
153
|
|
|
154
|
+
useEffect(() => {
|
|
155
|
+
const timeout = window.setTimeout(
|
|
156
|
+
() => setSearchQuery(inputValue),
|
|
157
|
+
inputValue.trim() ? 300 : 0,
|
|
158
|
+
);
|
|
159
|
+
return () => window.clearTimeout(timeout);
|
|
160
|
+
}, [inputValue]);
|
|
161
|
+
|
|
147
162
|
const visibleResults = useMemo(
|
|
148
163
|
() =>
|
|
149
164
|
filterPeopleResults(
|
|
150
|
-
contacts.data?.results
|
|
165
|
+
mergePeopleResults(contacts.data?.results, peopleSearch.data?.results),
|
|
151
166
|
inputValue,
|
|
152
167
|
selectedEmailSet,
|
|
153
168
|
),
|
|
154
|
-
[
|
|
169
|
+
[
|
|
170
|
+
contacts.data?.results,
|
|
171
|
+
inputValue,
|
|
172
|
+
peopleSearch.data?.results,
|
|
173
|
+
selectedEmailSet,
|
|
174
|
+
],
|
|
155
175
|
);
|
|
156
176
|
|
|
157
177
|
const canAddManual = parseEmails(inputValue).length > 0;
|
|
158
|
-
const searching =
|
|
159
|
-
|
|
178
|
+
const searching =
|
|
179
|
+
contacts.isLoading ||
|
|
180
|
+
contacts.isFetching ||
|
|
181
|
+
peopleSearch.isLoading ||
|
|
182
|
+
peopleSearch.isFetching;
|
|
183
|
+
const scopeRequired = Boolean(
|
|
184
|
+
contacts.data?.scopeRequired || peopleSearch.data?.scopeRequired,
|
|
185
|
+
);
|
|
160
186
|
const shouldShowPopover =
|
|
161
187
|
open &&
|
|
162
188
|
inputValue.trim().length > 0 &&
|
|
@@ -93,6 +93,51 @@ import {
|
|
|
93
93
|
import { markPopoverInteractOutside } from "@/lib/popover-click-guard";
|
|
94
94
|
import { shortcutModifierLabel } from "@/lib/utils";
|
|
95
95
|
|
|
96
|
+
const ZOOM_AFTER_CONNECT_EVENT_ID_KEY = "calendar.zoomAfterConnectEventId";
|
|
97
|
+
const ZOOM_AFTER_CONNECT_MAX_AGE_MS = 10 * 60 * 1000;
|
|
98
|
+
|
|
99
|
+
function getStoredZoomAfterConnectEventId(): string | null {
|
|
100
|
+
if (typeof window === "undefined") return null;
|
|
101
|
+
try {
|
|
102
|
+
const stored = window.sessionStorage.getItem(
|
|
103
|
+
ZOOM_AFTER_CONNECT_EVENT_ID_KEY,
|
|
104
|
+
);
|
|
105
|
+
if (!stored) return null;
|
|
106
|
+
const parsed = JSON.parse(stored) as {
|
|
107
|
+
eventId?: unknown;
|
|
108
|
+
startedAt?: unknown;
|
|
109
|
+
};
|
|
110
|
+
if (
|
|
111
|
+
typeof parsed.eventId === "string" &&
|
|
112
|
+
typeof parsed.startedAt === "number" &&
|
|
113
|
+
Date.now() - parsed.startedAt < ZOOM_AFTER_CONNECT_MAX_AGE_MS
|
|
114
|
+
) {
|
|
115
|
+
return parsed.eventId;
|
|
116
|
+
}
|
|
117
|
+
window.sessionStorage.removeItem(ZOOM_AFTER_CONNECT_EVENT_ID_KEY);
|
|
118
|
+
return null;
|
|
119
|
+
} catch {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function setStoredZoomAfterConnectEventId(eventId: string | null): void {
|
|
125
|
+
if (typeof window === "undefined") return;
|
|
126
|
+
try {
|
|
127
|
+
if (eventId) {
|
|
128
|
+
window.sessionStorage.setItem(
|
|
129
|
+
ZOOM_AFTER_CONNECT_EVENT_ID_KEY,
|
|
130
|
+
JSON.stringify({ eventId, startedAt: Date.now() }),
|
|
131
|
+
);
|
|
132
|
+
} else {
|
|
133
|
+
window.sessionStorage.removeItem(ZOOM_AFTER_CONNECT_EVENT_ID_KEY);
|
|
134
|
+
}
|
|
135
|
+
} catch {
|
|
136
|
+
// Storage can be unavailable in locked-down browsers; in-memory state still
|
|
137
|
+
// handles the normal popup path.
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
96
141
|
function formatDuration(start: string, end: string): string {
|
|
97
142
|
const totalMinutes = differenceInMinutes(parseISO(end), parseISO(start));
|
|
98
143
|
const hours = Math.floor(totalMinutes / 60);
|
|
@@ -403,6 +448,9 @@ export function EventDetailPopover({
|
|
|
403
448
|
const [pendingVideoProvider, setPendingVideoProvider] = useState<
|
|
404
449
|
"meet" | "zoom" | null
|
|
405
450
|
>(null);
|
|
451
|
+
const [zoomAfterConnectEventId, setZoomAfterConnectEventId] = useState<
|
|
452
|
+
string | null
|
|
453
|
+
>(() => getStoredZoomAfterConnectEventId());
|
|
406
454
|
const isOverlay = !!event.overlayEmail;
|
|
407
455
|
const ownerLabel = event.ownerName || event.overlayEmail;
|
|
408
456
|
|
|
@@ -686,45 +734,73 @@ export function EventDetailPopover({
|
|
|
686
734
|
})();
|
|
687
735
|
}, [event, isDraft, onDraftUpdate, promptGuestNotification, updateEvent]);
|
|
688
736
|
|
|
737
|
+
const addZoomToConnectedEvent = useCallback(() => {
|
|
738
|
+
if (!event.id || updateEvent.isPending) return;
|
|
739
|
+
|
|
740
|
+
if (isDraft) {
|
|
741
|
+
onDraftUpdate?.(event.id, { addZoom: true, addGoogleMeet: false });
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
setPendingVideoProvider("zoom");
|
|
746
|
+
void (async () => {
|
|
747
|
+
const updates = { addZoom: true };
|
|
748
|
+
const guestNotification = await promptGuestNotification({
|
|
749
|
+
event,
|
|
750
|
+
action: "update",
|
|
751
|
+
updates,
|
|
752
|
+
});
|
|
753
|
+
if (!guestNotification) {
|
|
754
|
+
setPendingVideoProvider(null);
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
updateEvent.mutate(
|
|
758
|
+
{
|
|
759
|
+
id: event.id,
|
|
760
|
+
accountEmail: event.accountEmail,
|
|
761
|
+
...updates,
|
|
762
|
+
...guestNotification,
|
|
763
|
+
},
|
|
764
|
+
{
|
|
765
|
+
onSuccess: () => toast(t("eventForm.zoomAdded")),
|
|
766
|
+
onError: (error) =>
|
|
767
|
+
toast.error(
|
|
768
|
+
error instanceof Error
|
|
769
|
+
? error.message
|
|
770
|
+
: t("eventForm.zoomAddFailed"),
|
|
771
|
+
),
|
|
772
|
+
onSettled: () => setPendingVideoProvider(null),
|
|
773
|
+
},
|
|
774
|
+
);
|
|
775
|
+
})();
|
|
776
|
+
}, [event, isDraft, onDraftUpdate, promptGuestNotification, t, updateEvent]);
|
|
777
|
+
|
|
778
|
+
useEffect(() => {
|
|
779
|
+
if (
|
|
780
|
+
!zoomStatus.data?.connected ||
|
|
781
|
+
!zoomAfterConnectEventId ||
|
|
782
|
+
zoomAfterConnectEventId !== event.id ||
|
|
783
|
+
updateEvent.isPending
|
|
784
|
+
) {
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
setZoomAfterConnectEventId(null);
|
|
789
|
+
setStoredZoomAfterConnectEventId(null);
|
|
790
|
+
addZoomToConnectedEvent();
|
|
791
|
+
}, [
|
|
792
|
+
addZoomToConnectedEvent,
|
|
793
|
+
event.id,
|
|
794
|
+
updateEvent.isPending,
|
|
795
|
+
zoomAfterConnectEventId,
|
|
796
|
+
zoomStatus.data?.connected,
|
|
797
|
+
]);
|
|
798
|
+
|
|
689
799
|
const handleAddZoom = useCallback(() => {
|
|
690
800
|
if (!event.id || updateEvent.isPending || connectZoom.isPending) return;
|
|
691
801
|
|
|
692
802
|
if (zoomStatus.data?.connected) {
|
|
693
|
-
|
|
694
|
-
onDraftUpdate?.(event.id, { addZoom: true, addGoogleMeet: false });
|
|
695
|
-
return;
|
|
696
|
-
}
|
|
697
|
-
setPendingVideoProvider("zoom");
|
|
698
|
-
void (async () => {
|
|
699
|
-
const updates = { addZoom: true };
|
|
700
|
-
const guestNotification = await promptGuestNotification({
|
|
701
|
-
event,
|
|
702
|
-
action: "update",
|
|
703
|
-
updates,
|
|
704
|
-
});
|
|
705
|
-
if (!guestNotification) {
|
|
706
|
-
setPendingVideoProvider(null);
|
|
707
|
-
return;
|
|
708
|
-
}
|
|
709
|
-
updateEvent.mutate(
|
|
710
|
-
{
|
|
711
|
-
id: event.id,
|
|
712
|
-
accountEmail: event.accountEmail,
|
|
713
|
-
...updates,
|
|
714
|
-
...guestNotification,
|
|
715
|
-
},
|
|
716
|
-
{
|
|
717
|
-
onSuccess: () => toast(t("eventForm.zoomAdded")),
|
|
718
|
-
onError: (error) =>
|
|
719
|
-
toast.error(
|
|
720
|
-
error instanceof Error
|
|
721
|
-
? error.message
|
|
722
|
-
: t("eventForm.zoomAddFailed"),
|
|
723
|
-
),
|
|
724
|
-
onSettled: () => setPendingVideoProvider(null),
|
|
725
|
-
},
|
|
726
|
-
);
|
|
727
|
-
})();
|
|
803
|
+
addZoomToConnectedEvent();
|
|
728
804
|
return;
|
|
729
805
|
}
|
|
730
806
|
|
|
@@ -733,21 +809,25 @@ export function EventDetailPopover({
|
|
|
733
809
|
return;
|
|
734
810
|
}
|
|
735
811
|
|
|
812
|
+
setZoomAfterConnectEventId(event.id);
|
|
813
|
+
setStoredZoomAfterConnectEventId(event.id);
|
|
736
814
|
connectZoom.mutate(undefined, {
|
|
737
815
|
onSuccess: () => toast(t("eventForm.zoomConnectionOpened")),
|
|
738
|
-
onError: (error) =>
|
|
816
|
+
onError: (error) => {
|
|
817
|
+
setZoomAfterConnectEventId(null);
|
|
818
|
+
setStoredZoomAfterConnectEventId(null);
|
|
739
819
|
toast.error(
|
|
740
820
|
error instanceof Error
|
|
741
821
|
? error.message
|
|
742
822
|
: t("eventForm.zoomConnectFailed"),
|
|
743
|
-
)
|
|
823
|
+
);
|
|
824
|
+
},
|
|
744
825
|
});
|
|
745
826
|
}, [
|
|
827
|
+
addZoomToConnectedEvent,
|
|
746
828
|
connectZoom,
|
|
747
829
|
event,
|
|
748
|
-
|
|
749
|
-
onDraftUpdate,
|
|
750
|
-
promptGuestNotification,
|
|
830
|
+
t,
|
|
751
831
|
updateEvent,
|
|
752
832
|
zoomStatus.data?.configured,
|
|
753
833
|
zoomStatus.data?.connected,
|
|
@@ -15,6 +15,8 @@ export interface PeopleSearchResponse {
|
|
|
15
15
|
|
|
16
16
|
const PEOPLE_CONTACTS_STALE_TIME = 10 * 60_000;
|
|
17
17
|
const PEOPLE_CONTACTS_GC_TIME = 30 * 60_000;
|
|
18
|
+
const PEOPLE_SEARCH_STALE_TIME = 60_000;
|
|
19
|
+
const PEOPLE_SEARCH_GC_TIME = 5 * 60_000;
|
|
18
20
|
|
|
19
21
|
export const PEOPLE_CONTACTS_QUERY_KEY = [
|
|
20
22
|
"action",
|
|
@@ -48,6 +50,42 @@ function matchRank(person: PeopleSearchResult, query: string) {
|
|
|
48
50
|
return 5;
|
|
49
51
|
}
|
|
50
52
|
|
|
53
|
+
export function mergePeopleResults(
|
|
54
|
+
...groups: Array<PeopleSearchResult[] | undefined>
|
|
55
|
+
) {
|
|
56
|
+
const people = new Map<string, PeopleSearchResult>();
|
|
57
|
+
|
|
58
|
+
for (const group of groups) {
|
|
59
|
+
for (const person of group ?? []) {
|
|
60
|
+
const email = person.email.trim();
|
|
61
|
+
const key = email.toLowerCase();
|
|
62
|
+
if (!key) continue;
|
|
63
|
+
|
|
64
|
+
const existing = people.get(key);
|
|
65
|
+
if (!existing) {
|
|
66
|
+
people.set(key, { ...person, email });
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (sourceRank(person.source) < sourceRank(existing.source)) {
|
|
71
|
+
existing.source = person.source;
|
|
72
|
+
}
|
|
73
|
+
if (
|
|
74
|
+
person.name &&
|
|
75
|
+
person.name !== person.email &&
|
|
76
|
+
(!existing.name || existing.name === existing.email)
|
|
77
|
+
) {
|
|
78
|
+
existing.name = person.name;
|
|
79
|
+
}
|
|
80
|
+
if (!existing.photoUrl && person.photoUrl) {
|
|
81
|
+
existing.photoUrl = person.photoUrl;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return Array.from(people.values());
|
|
87
|
+
}
|
|
88
|
+
|
|
51
89
|
export function filterPeopleResults(
|
|
52
90
|
people: PeopleSearchResult[],
|
|
53
91
|
query: string,
|
|
@@ -106,3 +144,20 @@ export function usePeopleContacts(enabled = true) {
|
|
|
106
144
|
refetchOnWindowFocus: false,
|
|
107
145
|
});
|
|
108
146
|
}
|
|
147
|
+
|
|
148
|
+
export function usePeopleSearch(query: string, enabled = true) {
|
|
149
|
+
const q = query.trim();
|
|
150
|
+
return useQuery({
|
|
151
|
+
queryKey: ["action", "search-people", { q, scope: "all" }],
|
|
152
|
+
queryFn: () =>
|
|
153
|
+
callAction<PeopleSearchResponse>(
|
|
154
|
+
"search-people",
|
|
155
|
+
{ q, scope: "all" },
|
|
156
|
+
{ method: "GET" },
|
|
157
|
+
),
|
|
158
|
+
enabled: enabled && q.length > 0,
|
|
159
|
+
staleTime: PEOPLE_SEARCH_STALE_TIME,
|
|
160
|
+
gcTime: PEOPLE_SEARCH_GC_TIME,
|
|
161
|
+
refetchOnWindowFocus: false,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
@@ -111,7 +111,11 @@ export default defineAction({
|
|
|
111
111
|
await setResumableSession(id, {
|
|
112
112
|
providerId: uploadProvider.id,
|
|
113
113
|
sessionId: session.sessionId,
|
|
114
|
-
meta: {
|
|
114
|
+
meta: {
|
|
115
|
+
...session.meta,
|
|
116
|
+
skipCompressionWait: true,
|
|
117
|
+
recordAsset: false,
|
|
118
|
+
},
|
|
115
119
|
bytesUploaded: 0,
|
|
116
120
|
lastCommittedIndex: -1,
|
|
117
121
|
});
|
|
@@ -98,6 +98,9 @@ function concatBytes(parts: Uint8Array[]): Uint8Array {
|
|
|
98
98
|
|
|
99
99
|
const RECORDING_TOO_LARGE_REASON =
|
|
100
100
|
"Recording is too large to process after automatic compression. Please update the app and try again, or record a shorter clip.";
|
|
101
|
+
const MEDIA_SERVE_VERIFICATION_TIMEOUT_MS = 8_000;
|
|
102
|
+
const MEDIA_SERVE_VERIFICATION_ATTEMPTS = 3;
|
|
103
|
+
const MEDIA_SERVE_VERIFICATION_BACKOFF_MS = 350;
|
|
101
104
|
|
|
102
105
|
function stateNumber(
|
|
103
106
|
value: Record<string, unknown> | null | undefined,
|
|
@@ -124,6 +127,78 @@ const cliBoolean = z.preprocess((value) => {
|
|
|
124
127
|
return value;
|
|
125
128
|
}, z.boolean());
|
|
126
129
|
|
|
130
|
+
function sleep(ms: number): Promise<void> {
|
|
131
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function shouldVerifyServedMediaUrl(value: string): boolean {
|
|
135
|
+
try {
|
|
136
|
+
const url = new URL(value);
|
|
137
|
+
return url.protocol === "http:" || url.protocol === "https:";
|
|
138
|
+
} catch {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async function responseHasReadableMediaBytes(
|
|
144
|
+
response: Response,
|
|
145
|
+
): Promise<boolean> {
|
|
146
|
+
const reader = response.body?.getReader();
|
|
147
|
+
if (!reader) {
|
|
148
|
+
const body = await response.arrayBuffer().catch(() => new ArrayBuffer(0));
|
|
149
|
+
return body.byteLength > 0;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
const { value } = await reader.read();
|
|
154
|
+
return (value?.byteLength ?? 0) > 0;
|
|
155
|
+
} catch {
|
|
156
|
+
return false;
|
|
157
|
+
} finally {
|
|
158
|
+
await reader.cancel().catch(() => undefined);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async function verifyServedMediaUrl(videoUrl: string): Promise<void> {
|
|
163
|
+
if (!shouldVerifyServedMediaUrl(videoUrl)) return;
|
|
164
|
+
|
|
165
|
+
let lastFailure = "media URL did not serve readable bytes";
|
|
166
|
+
for (
|
|
167
|
+
let attempt = 1;
|
|
168
|
+
attempt <= MEDIA_SERVE_VERIFICATION_ATTEMPTS;
|
|
169
|
+
attempt++
|
|
170
|
+
) {
|
|
171
|
+
const controller = new AbortController();
|
|
172
|
+
const timeout = setTimeout(
|
|
173
|
+
() => controller.abort(),
|
|
174
|
+
MEDIA_SERVE_VERIFICATION_TIMEOUT_MS,
|
|
175
|
+
);
|
|
176
|
+
try {
|
|
177
|
+
const response = await fetch(videoUrl, {
|
|
178
|
+
method: "GET",
|
|
179
|
+
headers: { Range: "bytes=0-1023" },
|
|
180
|
+
signal: controller.signal,
|
|
181
|
+
});
|
|
182
|
+
const statusOk = response.status === 200 || response.status === 206;
|
|
183
|
+
if (statusOk && (await responseHasReadableMediaBytes(response))) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
lastFailure = `media URL returned HTTP ${response.status}`;
|
|
187
|
+
if (response.status < 500) break;
|
|
188
|
+
} catch (err) {
|
|
189
|
+
lastFailure = err instanceof Error ? err.message : String(err);
|
|
190
|
+
} finally {
|
|
191
|
+
clearTimeout(timeout);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (attempt < MEDIA_SERVE_VERIFICATION_ATTEMPTS) {
|
|
195
|
+
await sleep(MEDIA_SERVE_VERIFICATION_BACKOFF_MS * attempt);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
throw new Error(`Upload was stored-but-unservable: ${lastFailure}`);
|
|
200
|
+
}
|
|
201
|
+
|
|
127
202
|
function queueBackgroundBuilderCompression(args: {
|
|
128
203
|
recordingId: string;
|
|
129
204
|
ownerEmail: string;
|
|
@@ -142,6 +217,44 @@ function queueBackgroundBuilderCompression(args: {
|
|
|
142
217
|
});
|
|
143
218
|
}
|
|
144
219
|
|
|
220
|
+
async function failStoredButUnservableRecording(params: {
|
|
221
|
+
id: string;
|
|
222
|
+
ownerEmail: string;
|
|
223
|
+
failureReason: string;
|
|
224
|
+
}): Promise<void> {
|
|
225
|
+
const { id, ownerEmail, failureReason } = params;
|
|
226
|
+
const now = new Date().toISOString();
|
|
227
|
+
const db = getDb();
|
|
228
|
+
await db
|
|
229
|
+
.update(schema.recordings)
|
|
230
|
+
.set({
|
|
231
|
+
status: "failed",
|
|
232
|
+
failureReason,
|
|
233
|
+
updatedAt: now,
|
|
234
|
+
})
|
|
235
|
+
.where(
|
|
236
|
+
and(
|
|
237
|
+
eq(schema.recordings.id, id),
|
|
238
|
+
ownerEmailMatches(schema.recordings.ownerEmail, ownerEmail),
|
|
239
|
+
),
|
|
240
|
+
);
|
|
241
|
+
const uploadStateRaw = await readAppState(`recording-upload-${id}`).catch(
|
|
242
|
+
() => null,
|
|
243
|
+
);
|
|
244
|
+
const uploadState =
|
|
245
|
+
uploadStateRaw && typeof uploadStateRaw === "object"
|
|
246
|
+
? (uploadStateRaw as Record<string, unknown>)
|
|
247
|
+
: {};
|
|
248
|
+
await writeAppState(`recording-upload-${id}`, {
|
|
249
|
+
...uploadState,
|
|
250
|
+
recordingId: id,
|
|
251
|
+
status: "failed",
|
|
252
|
+
failureReason,
|
|
253
|
+
updatedAt: now,
|
|
254
|
+
});
|
|
255
|
+
await writeAppState("refresh-signal", { ts: Date.now() });
|
|
256
|
+
}
|
|
257
|
+
|
|
145
258
|
// Flip recording to 'ready', seed transcript row, fire background transcript,
|
|
146
259
|
// emit clip.created. Used by both the resumable and buffered upload paths.
|
|
147
260
|
async function markRecordingReady(params: {
|
|
@@ -483,9 +596,21 @@ export default defineAction({
|
|
|
483
596
|
typeof resumableSession.meta.filename === "string"
|
|
484
597
|
? resumableSession.meta.filename
|
|
485
598
|
: "",
|
|
486
|
-
{ skipCompressionWait: true },
|
|
599
|
+
{ skipCompressionWait: true, recordAsset: false },
|
|
487
600
|
);
|
|
488
601
|
debugLog("[finalize] resumable upload completed", { id, videoUrl });
|
|
602
|
+
try {
|
|
603
|
+
await verifyServedMediaUrl(videoUrl);
|
|
604
|
+
} catch (err) {
|
|
605
|
+
const failureReason =
|
|
606
|
+
err instanceof Error ? err.message : String(err);
|
|
607
|
+
await failStoredButUnservableRecording({
|
|
608
|
+
id,
|
|
609
|
+
ownerEmail,
|
|
610
|
+
failureReason,
|
|
611
|
+
});
|
|
612
|
+
throw err;
|
|
613
|
+
}
|
|
489
614
|
const result = await markRecordingReady({
|
|
490
615
|
...readyParams,
|
|
491
616
|
videoUrl,
|
|
@@ -580,6 +705,7 @@ export default defineAction({
|
|
|
580
705
|
})
|
|
581
706
|
.where(eq(schema.recordings.id, id));
|
|
582
707
|
await writeAppState(`recording-upload-${id}`, {
|
|
708
|
+
...(uploadState ?? {}),
|
|
583
709
|
recordingId: id,
|
|
584
710
|
status: "failed",
|
|
585
711
|
failureReason,
|
|
@@ -841,6 +967,7 @@ export default defineAction({
|
|
|
841
967
|
mimeType,
|
|
842
968
|
ownerEmail,
|
|
843
969
|
skipCompressionWait: true,
|
|
970
|
+
recordAsset: false,
|
|
844
971
|
});
|
|
845
972
|
} catch (err) {
|
|
846
973
|
// Capture structured context so a "Builder.io upload failed (500)" can
|
|
@@ -993,6 +1120,18 @@ export default defineAction({
|
|
|
993
1120
|
videoUrl: upload.url,
|
|
994
1121
|
bytes: uploadData.byteLength,
|
|
995
1122
|
});
|
|
1123
|
+
try {
|
|
1124
|
+
await verifyServedMediaUrl(upload.url);
|
|
1125
|
+
} catch (err) {
|
|
1126
|
+
chunkKeysToPurge = [];
|
|
1127
|
+
const failureReason = err instanceof Error ? err.message : String(err);
|
|
1128
|
+
await failStoredButUnservableRecording({
|
|
1129
|
+
id,
|
|
1130
|
+
ownerEmail,
|
|
1131
|
+
failureReason,
|
|
1132
|
+
});
|
|
1133
|
+
throw err;
|
|
1134
|
+
}
|
|
996
1135
|
const result = await markRecordingReady({
|
|
997
1136
|
...readyParams,
|
|
998
1137
|
// Use the audio-probe-corrected value, not the raw client claim in
|
|
@@ -123,6 +123,36 @@ const SPEECH_ONLY_TRANSCRIPTION_INSTRUCTIONS =
|
|
|
123
123
|
"Auto-detect the spoken language from the audio. Transcribe only words spoken in the audio, in the same language they were spoken. Do not translate. Do not infer language from screen text, filenames, account settings, browser locale, or these instructions. Do not describe screen activity, UI changes, silence, music, or non-speech sounds. Return an empty transcript when there are no spoken words.";
|
|
124
124
|
const CLIPS_USER_PREFS_KEY = "clips-user-prefs";
|
|
125
125
|
const RECENT_PENDING_TRANSCRIPT_MS = 2 * 60 * 1000;
|
|
126
|
+
const BUILDER_TRANSCRIPTION_MIN_TIMEOUT_MS = 45_000;
|
|
127
|
+
const BUILDER_TRANSCRIPTION_MAX_TIMEOUT_MS = 65_000;
|
|
128
|
+
const BUILDER_TRANSCRIPTION_BASE_TIMEOUT_MS = 30_000;
|
|
129
|
+
const BUILDER_TRANSCRIPTION_PER_MINUTE_MS = 3_000;
|
|
130
|
+
|
|
131
|
+
function clampTimeoutMs(value: number): number {
|
|
132
|
+
return Math.max(
|
|
133
|
+
BUILDER_TRANSCRIPTION_MIN_TIMEOUT_MS,
|
|
134
|
+
Math.min(BUILDER_TRANSCRIPTION_MAX_TIMEOUT_MS, Math.floor(value)),
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function builderTranscriptionTimeoutMs(
|
|
139
|
+
durationMs: number | null | undefined,
|
|
140
|
+
): number {
|
|
141
|
+
const override = Number(process.env.CLIPS_BUILDER_TRANSCRIPTION_TIMEOUT_MS);
|
|
142
|
+
if (Number.isFinite(override) && override > 0) {
|
|
143
|
+
return clampTimeoutMs(override);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (!durationMs || !Number.isFinite(durationMs) || durationMs <= 0) {
|
|
147
|
+
return BUILDER_TRANSCRIPTION_MIN_TIMEOUT_MS;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const durationMinutes = Math.ceil(durationMs / 60_000);
|
|
151
|
+
return clampTimeoutMs(
|
|
152
|
+
BUILDER_TRANSCRIPTION_BASE_TIMEOUT_MS +
|
|
153
|
+
durationMinutes * BUILDER_TRANSCRIPTION_PER_MINUTE_MS,
|
|
154
|
+
);
|
|
155
|
+
}
|
|
126
156
|
|
|
127
157
|
// Bounded automatic retry for transient failures (ffmpeg timeout, transient
|
|
128
158
|
// provider network/5xx errors) — NOT for permanent failures like "no audio
|
|
@@ -1075,6 +1105,7 @@ const requestTranscriptAction = defineAction({
|
|
|
1075
1105
|
model: BUILDER_GEMINI_TRANSCRIPTION_MODEL,
|
|
1076
1106
|
diarize: false,
|
|
1077
1107
|
instructions: SPEECH_ONLY_TRANSCRIPTION_INSTRUCTIONS,
|
|
1108
|
+
timeoutMs: builderTranscriptionTimeoutMs(rec.durationMs),
|
|
1078
1109
|
});
|
|
1079
1110
|
|
|
1080
1111
|
const segments = (builderResult.segments ?? [])
|
|
@@ -116,6 +116,7 @@ export default defineAction({
|
|
|
116
116
|
args.filename ??
|
|
117
117
|
`thumb-${args.recordingId}.${mime.split("/")[1] ?? "png"}`,
|
|
118
118
|
ownerEmail,
|
|
119
|
+
recordAsset: false,
|
|
119
120
|
});
|
|
120
121
|
const url = uploaded?.url ?? args.dataUrl; // fall back to inline storage
|
|
121
122
|
basePatch.thumbnailUrl = url;
|
|
@@ -134,6 +135,7 @@ export default defineAction({
|
|
|
134
135
|
mimeType: mime || "image/gif",
|
|
135
136
|
filename: args.filename ?? `thumb-${args.recordingId}.gif`,
|
|
136
137
|
ownerEmail,
|
|
138
|
+
recordAsset: false,
|
|
137
139
|
});
|
|
138
140
|
const url = uploaded?.url ?? args.dataUrl;
|
|
139
141
|
basePatch.animatedThumbnailUrl = url;
|