@agent-native/core 0.92.0 → 0.92.1
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 +1 -1
- package/corpus/core/CHANGELOG.md +14 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/application-state/store.ts +12 -1
- package/corpus/core/src/client/AssistantChat.tsx +27 -14
- package/corpus/core/src/client/PoweredByBadge.tsx +1 -8
- package/corpus/core/src/client/agent-chat-adapter.ts +37 -10
- package/corpus/core/src/client/chat/widgets/DataTableWidget.tsx +52 -1
- package/corpus/core/src/client/db-admin/TableEditor.tsx +49 -0
- package/corpus/core/src/client/db-admin/export-utils.ts +13 -4
- package/corpus/core/src/client/db-admin/useAgentSync.ts +72 -0
- package/corpus/core/src/client/error-capture.ts +69 -7
- package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +5 -1
- package/corpus/core/src/client/extensions/ExtensionViewer.tsx +53 -8
- package/corpus/core/src/client/extensions/InlineExtensionFrame.tsx +5 -1
- package/corpus/core/src/client/extensions/portable-extension.ts +1 -0
- package/corpus/core/src/client/org/OrgSwitcher.tsx +12 -9
- package/corpus/core/src/client/org/TeamPage.tsx +77 -71
- package/corpus/core/src/client/settings/SettingsPanel.tsx +205 -52
- package/corpus/core/src/client/settings/SettingsSection.tsx +8 -1
- package/corpus/core/src/client/settings/SettingsTabsPage.tsx +25 -9
- package/corpus/core/src/db-admin/agent-tools.ts +8 -2
- package/corpus/core/src/db-admin/operations.ts +116 -4
- package/corpus/core/src/db-admin/routes.ts +1 -0
- package/corpus/core/src/db-admin/types.ts +4 -0
- package/corpus/core/src/extensions/html-shell.ts +5 -4
- package/corpus/core/src/extensions/routes.ts +10 -0
- package/corpus/core/src/navigation/index.ts +1 -1
- package/corpus/core/src/resources/handlers.ts +10 -8
- package/corpus/core/src/server/poll.ts +293 -8
- package/corpus/core/src/styles/agent-native.css +27 -0
- package/corpus/core/src/templates/default/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/core/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +7 -0
- package/corpus/core/src/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/core/src/templates/default/AGENTS.md +4 -2
- package/corpus/core/src/templates/headless/AGENTS.md +4 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/core/src/templates/workspace-core/AGENTS.md +7 -1
- package/corpus/core/src/templates/workspace-root/AGENTS.md +7 -1
- package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +10 -0
- package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/analytics/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/analytics/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/analytics/AGENTS.md +33 -14
- package/corpus/templates/analytics/actions/capture-test-error.ts +4 -0
- package/corpus/templates/analytics/actions/get-analytics-alert-rule-defaults.ts +23 -0
- package/corpus/templates/analytics/actions/get-error-issue.ts +1 -1
- package/corpus/templates/analytics/actions/list-analysis-revisions.ts +40 -0
- package/corpus/templates/analytics/actions/list-dashboard-revisions.ts +40 -0
- package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +299 -0
- package/corpus/templates/analytics/actions/navigate.ts +4 -2
- package/corpus/templates/analytics/actions/restore-analysis-revision.ts +43 -0
- package/corpus/templates/analytics/actions/restore-dashboard-revision.ts +68 -0
- package/corpus/templates/analytics/actions/save-analytics-alert-rule.ts +14 -0
- package/corpus/templates/analytics/actions/save-monitor.ts +1 -1
- package/corpus/templates/analytics/actions/view-screen.ts +24 -0
- package/corpus/templates/analytics/app/components/analysis/AnalysisHistoryPanel.tsx +181 -0
- package/corpus/templates/analytics/app/components/dashboard/DashboardHistoryPanel.tsx +184 -0
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +22 -16
- package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +27 -21
- package/corpus/templates/analytics/app/hooks/use-analysis-revisions.ts +43 -0
- package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +110 -0
- package/corpus/templates/analytics/app/hooks/use-dashboard-revisions.ts +43 -0
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +8 -3
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +64 -2
- package/corpus/templates/analytics/app/i18n-data.ts +783 -3
- package/corpus/templates/analytics/app/pages/Agents.tsx +359 -19
- package/corpus/templates/analytics/app/pages/Settings.tsx +3 -2
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +34 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +28 -0
- package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +18 -1
- package/corpus/templates/analytics/app/pages/monitoring/ErrorsPanel.tsx +7 -10
- package/corpus/templates/analytics/app/pages/monitoring/errors/IssueDetail.tsx +479 -23
- package/corpus/templates/analytics/app/pages/monitoring/errors/IssueList.tsx +0 -9
- package/corpus/templates/analytics/app/pages/monitoring/errors/i18n.ts +11 -0
- package/corpus/templates/analytics/app/pages/monitoring/errors/types.ts +9 -1
- package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorFormPage.tsx +6 -3
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +26 -30
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +9 -99
- package/corpus/templates/analytics/app/pages/settings/AlertRulesSettingsCard.tsx +262 -104
- package/corpus/templates/analytics/app/routes/team.tsx +1 -1
- package/corpus/templates/analytics/changelog/2026-07-08-admins-can-audit-dashboard-usage-ownership-and-cleanup-signa.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-agent-monitoring-stays-available-to-non-admins.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-alert-rules-are-easier-to-scan-expand-and-edit-from-settings.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-analytics-alert-forms-remember-last-email-recipients.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-analytics-alert-rules-can-now-use-per-rule-slack-and-webhook.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-dashboard-history-and-chat-context.md +5 -0
- package/corpus/templates/analytics/changelog/2026-07-08-dashboard-usage-now-counts-explorer-dashboard-traffic.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-demo-mode-session-emails-are-filtered-and-anonymized.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-error-issue-detail-adds-stack-traces-and-frequency-bars.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-error-issue-detail-now-shows-the-latest-occurrence-message-a.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-monitoring-errors-only-show-test-action-when-empty.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-production-session-replay-now-requires-private-blob-storage-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-shared-extension-links-now-show-a-clear-message-when-you-do-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-team-settings-show-access-controls-next-to-member-lists.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-08-uptime-monitors-now-use-a-10-second-request-timeout-by-defau.md +6 -0
- package/corpus/templates/analytics/server/db/schema-monitoring.ts +1 -1
- package/corpus/templates/analytics/server/db/schema.ts +56 -0
- package/corpus/templates/analytics/server/lib/analytics-alerts.ts +92 -0
- package/corpus/templates/analytics/server/lib/dashboards-store.ts +334 -5
- package/corpus/templates/analytics/server/lib/error-capture.ts +231 -36
- package/corpus/templates/analytics/server/lib/session-replay.ts +114 -8
- package/corpus/templates/analytics/server/lib/uptime-monitors.ts +5 -4
- package/corpus/templates/analytics/server/plugins/db.ts +112 -2
- package/corpus/templates/analytics/server/routes/api/dashboard-agent-context.json.get.ts +1 -0
- package/corpus/templates/assets/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/assets/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/assets/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/assets/AGENTS.md +4 -0
- package/corpus/templates/assets/app/routes/settings.tsx +1 -1
- package/corpus/templates/assets/app/routes/team.tsx +1 -1
- package/corpus/templates/brain/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/brain/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/brain/AGENTS.md +4 -0
- package/corpus/templates/brain/app/routes/team.tsx +1 -1
- package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/calendar/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/calendar/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/calendar/AGENTS.md +4 -0
- package/corpus/templates/calendar/app/components/calendar/DayView.tsx +11 -2
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +21 -8
- package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +7 -1
- package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +11 -2
- package/corpus/templates/calendar/app/lib/popover-click-guard.ts +48 -4
- package/corpus/templates/calendar/app/pages/Settings.tsx +1 -1
- package/corpus/templates/calendar/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/calendar/changelog/2026-07-08-clicking-empty-calendar-space-closes-an-open-event-popover-b.md +6 -0
- package/corpus/templates/chat/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/chat/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/chat/AGENTS.md +4 -0
- package/corpus/templates/chat/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/chat/app/routes/settings.tsx +2 -2
- package/corpus/templates/chat/app/routes/team.tsx +1 -1
- package/corpus/templates/clips/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/clips/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/clips/AGENTS.md +4 -0
- package/corpus/templates/clips/actions/finalize-recording.ts +9 -3
- package/corpus/templates/clips/actions/set-thumbnail.ts +11 -2
- package/corpus/templates/clips/app/components/meetings/canvas-editor.tsx +1 -7
- package/corpus/templates/clips/app/components/player/player-controls.tsx +21 -13
- package/corpus/templates/clips/app/components/player/video-player.tsx +30 -75
- package/corpus/templates/clips/app/i18n/ar-SA.ts +6 -5
- package/corpus/templates/clips/app/i18n/de-DE.ts +6 -6
- package/corpus/templates/clips/app/i18n/en-US.ts +6 -5
- package/corpus/templates/clips/app/i18n/es-ES.ts +6 -5
- package/corpus/templates/clips/app/i18n/fr-FR.ts +6 -6
- package/corpus/templates/clips/app/i18n/hi-IN.ts +6 -5
- package/corpus/templates/clips/app/i18n/ja-JP.ts +6 -5
- package/corpus/templates/clips/app/i18n/ko-KR.ts +6 -5
- package/corpus/templates/clips/app/i18n/pt-BR.ts +6 -5
- package/corpus/templates/clips/app/i18n/zh-CN.ts +6 -5
- package/corpus/templates/clips/app/i18n/zh-TW.ts +6 -5
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +51 -118
- package/corpus/templates/clips/changelog/2026-07-08-hosted-clip-uploads-now-clear-failed-buffered-chunks.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-hosted-recording-uploads-now-avoid-sql-chunk-storage.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-meeting-recaps-now-keep-summaries-action-items-and-transcrip.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-08-video-playback-controls-now-match-loom-style-5-second-skips-.md +6 -0
- package/corpus/templates/clips/server/lib/recording-upload-state.ts +63 -0
- package/corpus/templates/clips/server/lib/video-storage.ts +4 -0
- package/corpus/templates/clips/server/routes/api/recordings/[recordingId]/thumbnail.post.ts +19 -13
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +40 -1
- package/corpus/templates/content/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/content/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/content/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/content/AGENTS.md +4 -0
- package/corpus/templates/content/app/routes/_app.settings.tsx +2 -2
- package/corpus/templates/content/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/design/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/design/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/design/AGENTS.md +4 -0
- package/corpus/templates/design/actions/take-design-screenshot.ts +12 -9
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +57 -13
- package/corpus/templates/design/app/routes/team.tsx +1 -1
- package/corpus/templates/design/changelog/2026-07-08-local-images-added-to-designs-now-upload-to-file-storage-ins.md +6 -0
- package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/dispatch/AGENTS.md +4 -0
- package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/dispatch/app/routes/settings.tsx +2 -2
- package/corpus/templates/dispatch/app/routes/team.tsx +1 -1
- package/corpus/templates/forms/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/forms/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/forms/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/forms/AGENTS.md +4 -0
- package/corpus/templates/forms/app/routes/_app.settings.tsx +2 -2
- package/corpus/templates/forms/app/routes/_app.team.tsx +1 -1
- package/corpus/templates/forms/shared/navigation.ts +1 -1
- package/corpus/templates/macros/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/macros/AGENTS.md +4 -0
- package/corpus/templates/macros/app/routes/settings.tsx +2 -2
- package/corpus/templates/macros/app/routes/team.tsx +1 -1
- package/corpus/templates/mail/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/mail/.agents/skills/email-drafts/SKILL.md +1 -1
- package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/mail/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/mail/.agents/skills/storing-data/SKILL.md +5 -1
- package/corpus/templates/mail/AGENTS.md +4 -0
- package/corpus/templates/mail/changelog/2026-07-08-mail-attachments-in-hosted-environments-now-require-file-sto.md +6 -0
- package/corpus/templates/mail/server/handlers/media.ts +26 -1
- package/corpus/templates/mail/server/lib/outgoing-email.ts +24 -1
- package/corpus/templates/mail/server/lib/upload-store.ts +2 -1
- package/corpus/templates/plan/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/corpus/templates/plan/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/plan/AGENTS.md +4 -0
- package/corpus/templates/plan/app/hooks/use-navigation-state.ts +1 -1
- package/corpus/templates/plan/app/routes/settings.tsx +2 -2
- package/corpus/templates/plan/app/routes/team.tsx +1 -1
- package/corpus/templates/plan/changelog/2026-07-08-hosted-plan-images-now-require-connected-storage.md +6 -0
- package/corpus/templates/plan/server/lib/plan-assets.ts +33 -4
- package/corpus/templates/slides/.agents/skills/actions/SKILL.md +5 -0
- package/corpus/templates/slides/.agents/skills/security/SKILL.md +7 -0
- package/corpus/templates/slides/AGENTS.md +4 -0
- package/corpus/templates/slides/actions/generate-image-api.ts +15 -3
- package/corpus/templates/slides/app/routes/settings.tsx +2 -2
- package/corpus/templates/slides/app/routes/team.tsx +1 -1
- package/corpus/templates/slides/changelog/2026-07-08-generated-slide-images-now-return-hosted-file-storage-urls-i.md +6 -0
- package/corpus/templates/slides/shared/api.ts +1 -1
- package/dist/application-state/store.d.ts.map +1 -1
- package/dist/application-state/store.js +8 -2
- package/dist/application-state/store.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +24 -13
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/PoweredByBadge.d.ts +1 -1
- package/dist/client/PoweredByBadge.d.ts.map +1 -1
- package/dist/client/PoweredByBadge.js +3 -9
- package/dist/client/PoweredByBadge.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +28 -9
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/chat/widgets/DataTableWidget.d.ts.map +1 -1
- package/dist/client/chat/widgets/DataTableWidget.js +19 -2
- package/dist/client/chat/widgets/DataTableWidget.js.map +1 -1
- package/dist/client/db-admin/TableEditor.d.ts.map +1 -1
- package/dist/client/db-admin/TableEditor.js +19 -2
- package/dist/client/db-admin/TableEditor.js.map +1 -1
- package/dist/client/db-admin/export-utils.d.ts +2 -0
- package/dist/client/db-admin/export-utils.d.ts.map +1 -1
- package/dist/client/db-admin/export-utils.js +11 -3
- package/dist/client/db-admin/export-utils.js.map +1 -1
- package/dist/client/db-admin/useAgentSync.d.ts.map +1 -1
- package/dist/client/db-admin/useAgentSync.js +63 -0
- package/dist/client/db-admin/useAgentSync.js.map +1 -1
- package/dist/client/error-capture.d.ts.map +1 -1
- package/dist/client/error-capture.js +41 -7
- package/dist/client/error-capture.js.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.js +3 -1
- package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
- package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionViewer.js +32 -5
- package/dist/client/extensions/ExtensionViewer.js.map +1 -1
- package/dist/client/extensions/InlineExtensionFrame.d.ts.map +1 -1
- package/dist/client/extensions/InlineExtensionFrame.js +3 -1
- package/dist/client/extensions/InlineExtensionFrame.js.map +1 -1
- package/dist/client/extensions/portable-extension.d.ts.map +1 -1
- package/dist/client/extensions/portable-extension.js +1 -0
- package/dist/client/extensions/portable-extension.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts +1 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +11 -6
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +5 -5
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +37 -14
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/SettingsSection.js +1 -1
- package/dist/client/settings/SettingsSection.js.map +1 -1
- package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
- package/dist/client/settings/SettingsTabsPage.js +21 -10
- package/dist/client/settings/SettingsTabsPage.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/db-admin/agent-tools.d.ts.map +1 -1
- package/dist/db-admin/agent-tools.js +7 -2
- package/dist/db-admin/agent-tools.js.map +1 -1
- package/dist/db-admin/operations.d.ts.map +1 -1
- package/dist/db-admin/operations.js +90 -4
- package/dist/db-admin/operations.js.map +1 -1
- package/dist/db-admin/routes.d.ts.map +1 -1
- package/dist/db-admin/routes.js +1 -0
- package/dist/db-admin/routes.js.map +1 -1
- package/dist/db-admin/types.d.ts +4 -0
- package/dist/db-admin/types.d.ts.map +1 -1
- package/dist/db-admin/types.js.map +1 -1
- package/dist/extensions/html-shell.d.ts +5 -4
- package/dist/extensions/html-shell.d.ts.map +1 -1
- package/dist/extensions/html-shell.js.map +1 -1
- package/dist/extensions/routes.d.ts.map +1 -1
- package/dist/extensions/routes.js +8 -0
- package/dist/extensions/routes.js.map +1 -1
- package/dist/navigation/index.d.ts +1 -1
- package/dist/navigation/index.d.ts.map +1 -1
- package/dist/navigation/index.js +1 -1
- package/dist/navigation/index.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +6 -1
- package/dist/resources/handlers.d.ts.map +1 -1
- package/dist/resources/handlers.js +9 -8
- package/dist/resources/handlers.js.map +1 -1
- package/dist/server/poll.d.ts +12 -4
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +236 -9
- package/dist/server/poll.js.map +1 -1
- package/dist/styles/agent-native.css +27 -0
- package/dist/templates/default/.agents/skills/actions/SKILL.md +5 -0
- package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/dist/templates/default/.agents/skills/security/SKILL.md +7 -0
- package/dist/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
- package/dist/templates/default/AGENTS.md +4 -2
- package/dist/templates/headless/AGENTS.md +4 -0
- package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
- package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
- package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
- package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
- package/dist/templates/workspace-core/AGENTS.md +7 -1
- package/dist/templates/workspace-root/AGENTS.md +7 -1
- package/package.json +1 -1
- package/src/templates/default/.agents/skills/actions/SKILL.md +5 -0
- package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/src/templates/default/.agents/skills/security/SKILL.md +7 -0
- package/src/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
- package/src/templates/default/AGENTS.md +4 -2
- package/src/templates/headless/AGENTS.md +4 -0
- package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
- package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
- package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
- package/src/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
- package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
- package/src/templates/workspace-core/AGENTS.md +7 -1
- package/src/templates/workspace-root/AGENTS.md +7 -1
|
@@ -377,6 +377,11 @@ Most operations should be actions. You only need custom routes in `server/routes
|
|
|
377
377
|
- **Webhooks** — external services POST to a specific URL
|
|
378
378
|
- **OAuth callbacks** — redirect-based flows that need specific URL patterns
|
|
379
379
|
|
|
380
|
+
When the agent needs a durable image or file URL, call the core `upload-image`
|
|
381
|
+
action or use `uploadFile()` in server code. Do not write base64 into SQL,
|
|
382
|
+
markdown, deck/design JSON, or action results. `_agentImages` on action results
|
|
383
|
+
is for ephemeral vision previews only, not persistence.
|
|
384
|
+
|
|
380
385
|
If it's a standard CRUD operation, data query, or a wrapper around an action, use the action instead.
|
|
381
386
|
|
|
382
387
|
## Legacy Pattern (bare export)
|
|
@@ -74,6 +74,11 @@ Builder/internal data, or customer data in the action, UI, seed data, fixtures,
|
|
|
74
74
|
docs, prompts, or generated extension/app content. Register required secrets,
|
|
75
75
|
use OAuth helpers, or read scoped values from the vault/credential store.
|
|
76
76
|
|
|
77
|
+
If the feature involves attachments, images, recordings, screenshots, exports,
|
|
78
|
+
or other file-like payloads, design the upload path in the same change:
|
|
79
|
+
provider upload first, then URL/id/blob handle in SQL. Do not add base64/binary
|
|
80
|
+
columns or stuff files into `application_state`.
|
|
81
|
+
|
|
77
82
|
**If the action produces or lists a navigable resource**, add a `link` builder that returns `{ url: buildDeepLink({ app, view, params }), label }`. External coding agents and MCP hosts (Claude / ChatGPT / Claude Code / Cowork / Codex, over MCP/A2A) then surface an "Open in … →" deep link that drops the user back into the running UI focused on the record — for free. If a compatible MCP host should render an inline review/edit surface, also add `mcpApp` with `embedApp()` so the action embeds the real React app route instead of a one-off HTML UI. The `link` builder and `mcpApp` metadata must be pure and synchronous (no I/O). Any external-agent read/ingest action must be `http: { method: "GET" }` + `readOnly: true` + `publicAgent: { expose: true, readOnly: true, requiresAuth: true }`. See the `external-agents` skill.
|
|
78
83
|
|
|
79
84
|
### 3. Skills / Instructions
|
|
@@ -50,7 +50,7 @@ The agent modifies data in SQL, but the UI runs in the browser. SSE bridges same
|
|
|
50
50
|
|
|
51
51
|
For list/sidebar queries, use the same pattern — pass the counter into the queryKey of every list query you want to keep fresh.
|
|
52
52
|
|
|
53
|
-
4. **Fallback** polling calls `/_agent-native/poll?since=N`. It runs every 2 seconds until SSE is connected, then relaxes to 15 seconds (`SSE_FALLBACK_INTERVAL_MS`). If SSE is disabled or unavailable (e.g., edge/serverless deployments), polling continues at the 2 s cadence. Polling is the universal serverless fallback
|
|
53
|
+
4. **Fallback** polling calls `/_agent-native/poll?since=N`. It runs every 2 seconds until SSE is connected, then relaxes to 15 seconds (`SSE_FALLBACK_INTERVAL_MS`). If SSE is disabled or unavailable (e.g., edge/serverless deployments), polling continues at the 2 s cadence. Polling is the universal serverless fallback: new framework writes are read from the durable `sync_events` log, while the older DB timestamp scan remains as a slower safety net for direct SQL writes and older processes.
|
|
54
54
|
|
|
55
55
|
5. When the agent writes to the database, the version increments, SSE/polling detects it, and React Query refetches the affected queries.
|
|
56
56
|
|
|
@@ -51,6 +51,13 @@ export default defineAction({
|
|
|
51
51
|
|
|
52
52
|
The legacy `parameters:` field (plain JSON Schema) has no runtime validation — do not use it for new code.
|
|
53
53
|
|
|
54
|
+
## Large Payloads
|
|
55
|
+
|
|
56
|
+
Do not accept or persist unbounded base64/file blobs through actions, SQL writes,
|
|
57
|
+
or `application_state`. Route uploads through the file-upload provider and store
|
|
58
|
+
references. This prevents database bloat, slow hot paths, and accidental secret
|
|
59
|
+
or customer-data embedding inside binary payloads.
|
|
60
|
+
|
|
54
61
|
## SQL Injection
|
|
55
62
|
|
|
56
63
|
Never concatenate user input into SQL strings. Use Drizzle ORM's query builder (always safe) or parameterized queries:
|
|
@@ -6,6 +6,10 @@ workflow needs durable UI around the conversation.
|
|
|
6
6
|
|
|
7
7
|
## Core Rules
|
|
8
8
|
|
|
9
|
+
- Store large file/blob payloads in configured file/blob storage, not SQL: no
|
|
10
|
+
base64, `data:` URLs, images, video/audio, PDFs, ZIPs, screenshots,
|
|
11
|
+
thumbnails, or replay chunks in app tables, `application_state`, `settings`,
|
|
12
|
+
or `resources`; persist URLs, ids, or handles instead.
|
|
9
13
|
- Never hardcode API keys, tokens, webhook URLs, signing secrets, private Builder/internal data, customer data, or credential-looking literals. Use secrets/OAuth/runtime configuration and obvious placeholders in examples.
|
|
10
14
|
- Follow the root framework contract: data in SQL, actions first, application
|
|
11
15
|
state for navigation/selection, and shared agent chat for AI work.
|
|
@@ -49,7 +49,7 @@ export default function SettingsRoute() {
|
|
|
49
49
|
extraTabs={agentSettingsTabs}
|
|
50
50
|
generalSearchEntries={generalSearchEntries}
|
|
51
51
|
general={
|
|
52
|
-
<div className="mx-auto w-full max-w-
|
|
52
|
+
<div className="mx-auto w-full max-w-2xl space-y-6">
|
|
53
53
|
<p className="text-sm leading-6 text-muted-foreground">
|
|
54
54
|
{t("settings.description")}
|
|
55
55
|
</p>
|
|
@@ -79,7 +79,7 @@ export default function SettingsRoute() {
|
|
|
79
79
|
</div>
|
|
80
80
|
}
|
|
81
81
|
whatsNew={
|
|
82
|
-
<div className="mx-auto w-full max-w-
|
|
82
|
+
<div className="mx-auto w-full max-w-2xl">
|
|
83
83
|
<ChangelogSettingsCard markdown={changelog} />
|
|
84
84
|
</div>
|
|
85
85
|
}
|
|
@@ -377,6 +377,11 @@ Most operations should be actions. You only need custom routes in `server/routes
|
|
|
377
377
|
- **Webhooks** — external services POST to a specific URL
|
|
378
378
|
- **OAuth callbacks** — redirect-based flows that need specific URL patterns
|
|
379
379
|
|
|
380
|
+
When the agent needs a durable image or file URL, call the core `upload-image`
|
|
381
|
+
action or use `uploadFile()` in server code. Do not write base64 into SQL,
|
|
382
|
+
markdown, deck/design JSON, or action results. `_agentImages` on action results
|
|
383
|
+
is for ephemeral vision previews only, not persistence.
|
|
384
|
+
|
|
380
385
|
If it's a standard CRUD operation, data query, or a wrapper around an action, use the action instead.
|
|
381
386
|
|
|
382
387
|
## Legacy Pattern (bare export)
|
|
@@ -51,6 +51,13 @@ export default defineAction({
|
|
|
51
51
|
|
|
52
52
|
The legacy `parameters:` field (plain JSON Schema) has no runtime validation — do not use it for new code.
|
|
53
53
|
|
|
54
|
+
## Large Payloads
|
|
55
|
+
|
|
56
|
+
Do not accept or persist unbounded base64/file blobs through actions, SQL writes,
|
|
57
|
+
or `application_state`. Route uploads through the file-upload provider and store
|
|
58
|
+
references. This prevents database bloat, slow hot paths, and accidental secret
|
|
59
|
+
or customer-data embedding inside binary payloads.
|
|
60
|
+
|
|
54
61
|
## SQL Injection
|
|
55
62
|
|
|
56
63
|
Never concatenate user input into SQL strings. Use Drizzle ORM's query builder (always safe) or parameterized queries:
|
|
@@ -9,6 +9,10 @@ Detailed media, meeting, dictation, editing, and sharing rules live in
|
|
|
9
9
|
|
|
10
10
|
## Core Rules
|
|
11
11
|
|
|
12
|
+
- Store large file/blob payloads in configured file/blob storage, not SQL: no
|
|
13
|
+
base64, `data:` URLs, images, video/audio, PDFs, ZIPs, screenshots,
|
|
14
|
+
thumbnails, or replay chunks in app tables, `application_state`, `settings`,
|
|
15
|
+
or `resources`; persist URLs, ids, or handles instead.
|
|
12
16
|
- Never hardcode API keys, tokens, webhook URLs, signing secrets, private Builder/internal data, customer data, or credential-looking literals. Use secrets/OAuth/runtime configuration and obvious placeholders in examples.
|
|
13
17
|
- Use actions for recording metadata, transcripts, cleanup, summaries, chapters,
|
|
14
18
|
comments, spaces/folders, meetings, and sharing. Do not bypass access helpers.
|
|
@@ -483,8 +483,9 @@ export default defineAction({
|
|
|
483
483
|
// server-side half of the 70 GB memory leak — each failed finalize
|
|
484
484
|
// orphaned one recording's worth of chunks, and with base64 overhead
|
|
485
485
|
// a 30-minute recording is ~1.5 GB per corpse. Missing storage is the
|
|
486
|
-
// exception:
|
|
487
|
-
// provider and this action runs again.
|
|
486
|
+
// exception: local-dev storage gaps can keep chunks recoverable until the
|
|
487
|
+
// user connects a provider and this action runs again. Hosted SQL must
|
|
488
|
+
// never retain scratch video blobs.
|
|
488
489
|
let chunkKeysToPurge: string[] = [];
|
|
489
490
|
try {
|
|
490
491
|
const [existing] = await db
|
|
@@ -1123,7 +1124,12 @@ export default defineAction({
|
|
|
1123
1124
|
try {
|
|
1124
1125
|
await verifyServedMediaUrl(upload.url);
|
|
1125
1126
|
} catch (err) {
|
|
1126
|
-
|
|
1127
|
+
if (!requiresConfiguredVideoStorage()) {
|
|
1128
|
+
// Local dev can keep scratch chunks so the user can retry after fixing
|
|
1129
|
+
// a local storage/server issue. Hosted SQL must not keep video blobs in
|
|
1130
|
+
// application_state after a provider returned an unservable URL.
|
|
1131
|
+
chunkKeysToPurge = [];
|
|
1132
|
+
}
|
|
1127
1133
|
const failureReason = err instanceof Error ? err.message : String(err);
|
|
1128
1134
|
await failStoredButUnservableRecording({
|
|
1129
1135
|
id,
|
|
@@ -28,9 +28,12 @@ import { z } from "zod";
|
|
|
28
28
|
import { parseEdits, serializeEdits } from "../app/lib/timestamp-mapping.js";
|
|
29
29
|
import { getDb, schema } from "../server/db/index.js";
|
|
30
30
|
import { getCurrentOwnerEmail } from "../server/lib/recordings.js";
|
|
31
|
+
import { requiresConfiguredVideoStorage } from "../server/lib/video-storage.js";
|
|
31
32
|
import { assertNativeRecordingMedia } from "./lib/native-media.js";
|
|
32
33
|
|
|
33
34
|
const MAX_CAS_ATTEMPTS = 5;
|
|
35
|
+
const THUMBNAIL_STORAGE_REQUIRED_REASON =
|
|
36
|
+
"Thumbnail storage is not connected yet. Connect Builder.io or configure S3-compatible storage to save thumbnails.";
|
|
34
37
|
|
|
35
38
|
function decodeDataUrl(dataUrl: string): { bytes: Uint8Array; mime: string } {
|
|
36
39
|
const match = /^data:([^;]+);base64,(.+)$/.exec(dataUrl);
|
|
@@ -118,7 +121,10 @@ export default defineAction({
|
|
|
118
121
|
ownerEmail,
|
|
119
122
|
recordAsset: false,
|
|
120
123
|
});
|
|
121
|
-
|
|
124
|
+
if (!uploaded?.url && requiresConfiguredVideoStorage()) {
|
|
125
|
+
throw new Error(THUMBNAIL_STORAGE_REQUIRED_REASON);
|
|
126
|
+
}
|
|
127
|
+
const url = uploaded?.url ?? args.dataUrl; // Local SQL fallback only.
|
|
122
128
|
basePatch.thumbnailUrl = url;
|
|
123
129
|
thumbnailPatch = { kind: "url", value: url };
|
|
124
130
|
} else if (args.kind === "frame") {
|
|
@@ -137,7 +143,10 @@ export default defineAction({
|
|
|
137
143
|
ownerEmail,
|
|
138
144
|
recordAsset: false,
|
|
139
145
|
});
|
|
140
|
-
|
|
146
|
+
if (!uploaded?.url && requiresConfiguredVideoStorage()) {
|
|
147
|
+
throw new Error(THUMBNAIL_STORAGE_REQUIRED_REASON);
|
|
148
|
+
}
|
|
149
|
+
const url = uploaded?.url ?? args.dataUrl; // Local SQL fallback only.
|
|
141
150
|
basePatch.animatedThumbnailUrl = url;
|
|
142
151
|
basePatch.animatedThumbnailEnabled = true;
|
|
143
152
|
gifPatch = {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { useT } from "@agent-native/core/client";
|
|
2
|
-
import { IconWand } from "@tabler/icons-react";
|
|
3
2
|
import { useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
4
3
|
|
|
5
4
|
import { Textarea } from "@/components/ui/textarea";
|
|
@@ -279,10 +278,5 @@ function AiBulletsBlock({
|
|
|
279
278
|
/* -------------------------------------------------------------------------- */
|
|
280
279
|
|
|
281
280
|
function AiTabIndicator() {
|
|
282
|
-
return
|
|
283
|
-
<div className="flex items-center gap-1 text-[10px] uppercase tracking-wide text-muted-foreground/60 opacity-0 group-hover:opacity-100 transition-opacity">
|
|
284
|
-
<IconWand className="h-3 w-3" />
|
|
285
|
-
<span>AI</span>
|
|
286
|
-
</div>
|
|
287
|
-
);
|
|
281
|
+
return null;
|
|
288
282
|
}
|
|
@@ -36,7 +36,7 @@ import { cn } from "@/lib/utils";
|
|
|
36
36
|
import { Scrubber, msToClock } from "./scrubber";
|
|
37
37
|
|
|
38
38
|
export const SPEED_OPTIONS = PLAYBACK_SPEED_OPTIONS;
|
|
39
|
-
export const PLAYER_SEEK_STEP_MS =
|
|
39
|
+
export const PLAYER_SEEK_STEP_MS = 5_000;
|
|
40
40
|
|
|
41
41
|
export interface PlayerControlsProps {
|
|
42
42
|
isPlaying: boolean;
|
|
@@ -120,14 +120,6 @@ export function PlayerControls(props: PlayerControlsProps) {
|
|
|
120
120
|
/>
|
|
121
121
|
|
|
122
122
|
<div className="flex min-w-0 items-center gap-1.5 text-white">
|
|
123
|
-
<IconBtn
|
|
124
|
-
onClick={() => onSeekRelative(-PLAYER_SEEK_STEP_MS)}
|
|
125
|
-
tooltip="Back 15 seconds"
|
|
126
|
-
ariaLabel="Back 15 seconds"
|
|
127
|
-
>
|
|
128
|
-
<SkipIcon direction="back" />
|
|
129
|
-
</IconBtn>
|
|
130
|
-
|
|
131
123
|
<IconBtn
|
|
132
124
|
onClick={onPlayPause}
|
|
133
125
|
tooltip={isPlaying ? "Pause (K)" : "Play (K)"}
|
|
@@ -140,15 +132,24 @@ export function PlayerControls(props: PlayerControlsProps) {
|
|
|
140
132
|
)}
|
|
141
133
|
</IconBtn>
|
|
142
134
|
|
|
135
|
+
<IconBtn
|
|
136
|
+
onClick={() => onSeekRelative(-PLAYER_SEEK_STEP_MS)}
|
|
137
|
+
tooltip="Back 5 seconds"
|
|
138
|
+
ariaLabel="Back 5 seconds"
|
|
139
|
+
>
|
|
140
|
+
<SkipIcon direction="back" />
|
|
141
|
+
</IconBtn>
|
|
142
|
+
|
|
143
143
|
<IconBtn
|
|
144
144
|
onClick={() => onSeekRelative(PLAYER_SEEK_STEP_MS)}
|
|
145
|
-
tooltip="Forward
|
|
146
|
-
ariaLabel="Forward
|
|
145
|
+
tooltip="Forward 5 seconds"
|
|
146
|
+
ariaLabel="Forward 5 seconds"
|
|
147
147
|
>
|
|
148
148
|
<SkipIcon direction="forward" />
|
|
149
149
|
</IconBtn>
|
|
150
150
|
|
|
151
151
|
<div
|
|
152
|
+
data-player-ui
|
|
152
153
|
className="relative flex shrink-0 items-center"
|
|
153
154
|
onMouseEnter={() => setVolumePopoverOpen(true)}
|
|
154
155
|
onMouseLeave={() => setVolumePopoverOpen(false)}
|
|
@@ -158,6 +159,7 @@ export function PlayerControls(props: PlayerControlsProps) {
|
|
|
158
159
|
<Popover open={volumePopoverOpen} onOpenChange={setVolumePopoverOpen}>
|
|
159
160
|
<PopoverTrigger asChild>
|
|
160
161
|
<button
|
|
162
|
+
data-player-ui
|
|
161
163
|
type="button"
|
|
162
164
|
onClick={onToggleMute}
|
|
163
165
|
className="flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-white hover:bg-white/10"
|
|
@@ -171,6 +173,7 @@ export function PlayerControls(props: PlayerControlsProps) {
|
|
|
171
173
|
</button>
|
|
172
174
|
</PopoverTrigger>
|
|
173
175
|
<PopoverContent
|
|
176
|
+
data-player-ui
|
|
174
177
|
side="top"
|
|
175
178
|
align="center"
|
|
176
179
|
sideOffset={8}
|
|
@@ -219,7 +222,10 @@ export function PlayerControls(props: PlayerControlsProps) {
|
|
|
219
222
|
<Tooltip>
|
|
220
223
|
<TooltipTrigger asChild>
|
|
221
224
|
<DropdownMenuTrigger asChild>
|
|
222
|
-
<button
|
|
225
|
+
<button
|
|
226
|
+
data-player-ui
|
|
227
|
+
className="h-8 shrink-0 rounded-md px-2 text-xs font-medium tabular-nums hover:bg-white/10"
|
|
228
|
+
>
|
|
223
229
|
{speed}x
|
|
224
230
|
</button>
|
|
225
231
|
</DropdownMenuTrigger>
|
|
@@ -227,6 +233,7 @@ export function PlayerControls(props: PlayerControlsProps) {
|
|
|
227
233
|
<TooltipContent>{t("playerControls.playbackSpeed")}</TooltipContent>
|
|
228
234
|
</Tooltip>
|
|
229
235
|
<DropdownMenuContent
|
|
236
|
+
data-player-ui
|
|
230
237
|
align="end"
|
|
231
238
|
side="top"
|
|
232
239
|
className="min-w-[90px]"
|
|
@@ -298,6 +305,7 @@ function IconBtn({
|
|
|
298
305
|
<Tooltip>
|
|
299
306
|
<TooltipTrigger asChild>
|
|
300
307
|
<button
|
|
308
|
+
data-player-ui
|
|
301
309
|
onClick={onClick}
|
|
302
310
|
aria-label={ariaLabel ?? tooltip}
|
|
303
311
|
className={cn(
|
|
@@ -319,7 +327,7 @@ function SkipIcon({ direction }: { direction: "back" | "forward" }) {
|
|
|
319
327
|
<IconPlayerSkipForward
|
|
320
328
|
className={cn("h-5 w-5", direction === "back" && "rotate-180")}
|
|
321
329
|
/>
|
|
322
|
-
<span className="absolute text-[7px] font-bold leading-none">
|
|
330
|
+
<span className="absolute text-[7px] font-bold leading-none">5</span>
|
|
323
331
|
</span>
|
|
324
332
|
);
|
|
325
333
|
}
|
|
@@ -8,11 +8,7 @@ import {
|
|
|
8
8
|
LOOM_START_MS_QUERY_PARAM,
|
|
9
9
|
loomEmbedUrlWithTimestamp,
|
|
10
10
|
} from "@shared/loom";
|
|
11
|
-
import {
|
|
12
|
-
IconBolt,
|
|
13
|
-
IconPlayerPlay,
|
|
14
|
-
IconPlayerSkipForward,
|
|
15
|
-
} from "@tabler/icons-react";
|
|
11
|
+
import { IconBolt, IconPlayerPlay } from "@tabler/icons-react";
|
|
16
12
|
import {
|
|
17
13
|
forwardRef,
|
|
18
14
|
useCallback,
|
|
@@ -51,11 +47,7 @@ import { cn } from "@/lib/utils";
|
|
|
51
47
|
|
|
52
48
|
import { CaptionsOverlay } from "./captions-overlay";
|
|
53
49
|
import { CtaButton } from "./cta-button";
|
|
54
|
-
import {
|
|
55
|
-
PLAYER_SEEK_STEP_MS,
|
|
56
|
-
PlayerControls,
|
|
57
|
-
SPEED_OPTIONS,
|
|
58
|
-
} from "./player-controls";
|
|
50
|
+
import { PlayerControls, SPEED_OPTIONS } from "./player-controls";
|
|
59
51
|
|
|
60
52
|
function resolveLocalUrl(url: string | null | undefined): string | undefined {
|
|
61
53
|
if (!url) return undefined;
|
|
@@ -571,6 +563,17 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
|
|
|
571
563
|
requestPlay();
|
|
572
564
|
}, [isPlaying, pauseVideo, requestPlay]);
|
|
573
565
|
|
|
566
|
+
const activateVideoSurface = useCallback(() => {
|
|
567
|
+
const v = videoRef.current;
|
|
568
|
+
if (!v) return;
|
|
569
|
+
if (!v.paused || isPlaying) {
|
|
570
|
+
pauseVideo();
|
|
571
|
+
} else {
|
|
572
|
+
requestPlay();
|
|
573
|
+
}
|
|
574
|
+
bumpControls();
|
|
575
|
+
}, [bumpControls, isPlaying, pauseVideo, requestPlay]);
|
|
576
|
+
|
|
574
577
|
const handlePlayerPointerDown = useCallback(
|
|
575
578
|
(e: React.PointerEvent<HTMLDivElement>) => {
|
|
576
579
|
if (
|
|
@@ -607,10 +610,9 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
|
|
|
607
610
|
|
|
608
611
|
e.preventDefault();
|
|
609
612
|
suppressNextClickRef.current = true;
|
|
610
|
-
|
|
611
|
-
bumpControls();
|
|
613
|
+
activateVideoSurface();
|
|
612
614
|
},
|
|
613
|
-
[
|
|
615
|
+
[activateVideoSurface, isLoomEmbed],
|
|
614
616
|
);
|
|
615
617
|
|
|
616
618
|
const handlePlayerPointerCancel = useCallback(
|
|
@@ -1109,10 +1111,11 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
|
|
|
1109
1111
|
suppressNextClickRef.current = false;
|
|
1110
1112
|
return;
|
|
1111
1113
|
}
|
|
1112
|
-
// Clicking the video toggles
|
|
1114
|
+
// Clicking the video surface toggles playback, but actual controls
|
|
1115
|
+
// keep their own behavior.
|
|
1113
1116
|
if (isPlayerUiTarget(e.target)) return;
|
|
1114
1117
|
if (isLoomEmbed) return;
|
|
1115
|
-
|
|
1118
|
+
activateVideoSurface();
|
|
1116
1119
|
}}
|
|
1117
1120
|
>
|
|
1118
1121
|
{isLoomEmbed && loomIframeSrc ? (
|
|
@@ -1397,7 +1400,6 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
|
|
|
1397
1400
|
requestPlay();
|
|
1398
1401
|
}}
|
|
1399
1402
|
onSpeedChange={applySpeed}
|
|
1400
|
-
onSeekRelative={seekByMs}
|
|
1401
1403
|
menuPortalContainer={fullscreenMenuContainer}
|
|
1402
1404
|
/>
|
|
1403
1405
|
) : null}
|
|
@@ -1442,7 +1444,6 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
|
|
|
1442
1444
|
{/* Controls */}
|
|
1443
1445
|
{!hideChrome && !isLoomEmbed ? (
|
|
1444
1446
|
<div
|
|
1445
|
-
data-player-ui
|
|
1446
1447
|
className={cn(
|
|
1447
1448
|
"absolute inset-x-0 bottom-0 z-20 transition-opacity duration-200",
|
|
1448
1449
|
showControls ? "opacity-100" : "opacity-0 pointer-events-none",
|
|
@@ -1511,7 +1512,6 @@ function CenterPlaybackOverlay({
|
|
|
1511
1512
|
playError,
|
|
1512
1513
|
onPlay,
|
|
1513
1514
|
onSpeedChange,
|
|
1514
|
-
onSeekRelative,
|
|
1515
1515
|
menuPortalContainer,
|
|
1516
1516
|
}: {
|
|
1517
1517
|
mode: "loading" | "ready";
|
|
@@ -1521,7 +1521,6 @@ function CenterPlaybackOverlay({
|
|
|
1521
1521
|
playError: string | null;
|
|
1522
1522
|
onPlay: () => void;
|
|
1523
1523
|
onSpeedChange: (rate: number) => void;
|
|
1524
|
-
onSeekRelative: (deltaMs: number) => void;
|
|
1525
1524
|
menuPortalContainer?: HTMLElement | null;
|
|
1526
1525
|
}) {
|
|
1527
1526
|
const t = useT();
|
|
@@ -1546,30 +1545,18 @@ function CenterPlaybackOverlay({
|
|
|
1546
1545
|
</div>
|
|
1547
1546
|
) : (
|
|
1548
1547
|
<>
|
|
1549
|
-
<
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
onPlay();
|
|
1562
|
-
}}
|
|
1563
|
-
className="pointer-events-auto flex h-[clamp(3rem,13cqw,6rem)] w-[clamp(3rem,13cqw,6rem)] items-center justify-center rounded-full bg-white text-black shadow-2xl ring-1 ring-white/35 transition-transform duration-150 hover:scale-105 hover:bg-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-offset-2 focus-visible:ring-offset-black"
|
|
1564
|
-
>
|
|
1565
|
-
<IconPlayerPlay className="ml-[6%] h-[clamp(1.5rem,6.5cqw,3rem)] w-[clamp(1.5rem,6.5cqw,3rem)] fill-current" />
|
|
1566
|
-
</button>
|
|
1567
|
-
<CenterSeekButton
|
|
1568
|
-
direction="forward"
|
|
1569
|
-
ariaLabel="Forward 15 seconds"
|
|
1570
|
-
onClick={() => onSeekRelative(PLAYER_SEEK_STEP_MS)}
|
|
1571
|
-
/>
|
|
1572
|
-
</div>
|
|
1548
|
+
<button
|
|
1549
|
+
data-player-ui
|
|
1550
|
+
type="button"
|
|
1551
|
+
aria-label={t("videoPlayer.playClip")}
|
|
1552
|
+
onClick={(e) => {
|
|
1553
|
+
e.stopPropagation();
|
|
1554
|
+
onPlay();
|
|
1555
|
+
}}
|
|
1556
|
+
className="pointer-events-auto flex h-[clamp(3rem,13cqw,6rem)] w-[clamp(3rem,13cqw,6rem)] items-center justify-center rounded-full bg-white text-black shadow-2xl ring-1 ring-white/35 transition-transform duration-150 hover:scale-105 hover:bg-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-offset-2 focus-visible:ring-offset-black"
|
|
1557
|
+
>
|
|
1558
|
+
<IconPlayerPlay className="ml-[6%] h-[clamp(1.5rem,6.5cqw,3rem)] w-[clamp(1.5rem,6.5cqw,3rem)] fill-current" />
|
|
1559
|
+
</button>
|
|
1573
1560
|
|
|
1574
1561
|
<div
|
|
1575
1562
|
data-player-ui
|
|
@@ -1634,38 +1621,6 @@ function CenterPlaybackOverlay({
|
|
|
1634
1621
|
);
|
|
1635
1622
|
}
|
|
1636
1623
|
|
|
1637
|
-
function CenterSeekButton({
|
|
1638
|
-
direction,
|
|
1639
|
-
ariaLabel,
|
|
1640
|
-
onClick,
|
|
1641
|
-
}: {
|
|
1642
|
-
direction: "back" | "forward";
|
|
1643
|
-
ariaLabel: string;
|
|
1644
|
-
onClick: () => void;
|
|
1645
|
-
}) {
|
|
1646
|
-
return (
|
|
1647
|
-
<button
|
|
1648
|
-
data-player-ui
|
|
1649
|
-
type="button"
|
|
1650
|
-
aria-label={ariaLabel}
|
|
1651
|
-
onClick={(e) => {
|
|
1652
|
-
e.stopPropagation();
|
|
1653
|
-
onClick();
|
|
1654
|
-
}}
|
|
1655
|
-
className="pointer-events-auto flex h-[clamp(2.5rem,9cqw,4rem)] w-[clamp(2.5rem,9cqw,4rem)] items-center justify-center rounded-full bg-black/70 text-white shadow-xl ring-1 ring-white/20 backdrop-blur-md transition-transform duration-150 hover:scale-105 hover:bg-black/80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-offset-2 focus-visible:ring-offset-black"
|
|
1656
|
-
>
|
|
1657
|
-
<span className="relative flex h-[clamp(1.25rem,4.5cqw,2rem)] w-[clamp(1.25rem,4.5cqw,2rem)] items-center justify-center">
|
|
1658
|
-
<IconPlayerSkipForward
|
|
1659
|
-
className={cn("h-full w-full", direction === "back" && "rotate-180")}
|
|
1660
|
-
/>
|
|
1661
|
-
<span className="absolute text-[clamp(0.45rem,1.8cqw,0.7rem)] font-bold leading-none">
|
|
1662
|
-
15
|
|
1663
|
-
</span>
|
|
1664
|
-
</span>
|
|
1665
|
-
</button>
|
|
1666
|
-
);
|
|
1667
|
-
}
|
|
1668
|
-
|
|
1669
1624
|
/**
|
|
1670
1625
|
* Clamp a millisecond seek target to a value the browser will actually accept.
|
|
1671
1626
|
*
|
|
@@ -307,7 +307,7 @@ const messages = {
|
|
|
307
307
|
unassigned: "غير معين",
|
|
308
308
|
them: "هم",
|
|
309
309
|
me: "أنا",
|
|
310
|
-
regeneratingNotes: "
|
|
310
|
+
regeneratingNotes: "جارٍ إعادة إنشاء الملخص",
|
|
311
311
|
meetingRemoved: "تمت إزالة الاجتماع",
|
|
312
312
|
couldNotRemoveMeeting: "تعذرت إزالة الاجتماع",
|
|
313
313
|
couldNotLoadMeeting: "تعذر تحميل هذا الاجتماع.",
|
|
@@ -315,8 +315,8 @@ const messages = {
|
|
|
315
315
|
couldNotCopyTranscript: "تعذر نسخ النص",
|
|
316
316
|
allMeetings: "جميع الاجتماعات",
|
|
317
317
|
live: "يعيش",
|
|
318
|
-
generatingNotesInline: "جارٍ إنشاء
|
|
319
|
-
regenerateNotes: "إعادة إنشاء
|
|
318
|
+
generatingNotesInline: "جارٍ إنشاء الملخص…",
|
|
319
|
+
regenerateNotes: "إعادة إنشاء الملخص",
|
|
320
320
|
share: "يشارك",
|
|
321
321
|
meetingOptions: "خيارات الاجتماع",
|
|
322
322
|
removeMeeting: "إزالة الاجتماع",
|
|
@@ -329,12 +329,13 @@ const messages = {
|
|
|
329
329
|
desktopHint:
|
|
330
330
|
"لبدء الملاحظات، افتح Clips Desktop من شريط القوائم واختر Start Meeting Notes، أو انقر على Start notes عند ظهور التذكير. يلتقط Clips الميكروفون وصوت النظام ويكتب النص هنا.",
|
|
331
331
|
getDesktopApp: "احصل على تطبيق سطح المكتب",
|
|
332
|
-
generateNotesFailed: "تعذر إنشاء
|
|
332
|
+
generateNotesFailed: "تعذر إنشاء الملخص. حاول ثانية.",
|
|
333
333
|
attendee_one: "الحضور {{count}}",
|
|
334
334
|
attendee_other: "الحضور {{count}}",
|
|
335
335
|
joinCall: "الانضمام إلى المكالمة",
|
|
336
336
|
myNotes: "ملاحظاتي",
|
|
337
337
|
aiNotes: "تلاحظ منظمة العفو الدولية",
|
|
338
|
+
summary: "الملخص",
|
|
338
339
|
actionItems: "عناصر العمل",
|
|
339
340
|
working: "عمل…",
|
|
340
341
|
noActionItems:
|
|
@@ -907,7 +908,7 @@ const messages = {
|
|
|
907
908
|
unavailable: "هذا الاجتماع خاص أو لم يعد متاحًا.",
|
|
908
909
|
tryClips: "جرّب Clips",
|
|
909
910
|
attendees: "{{count}} حاضرون",
|
|
910
|
-
noAiNotes: "لم يتم إنشاء
|
|
911
|
+
noAiNotes: "لم يتم إنشاء ملخص لهذا الاجتماع بعد.",
|
|
911
912
|
summary: "الملخص",
|
|
912
913
|
keyPoints: "النقاط الرئيسية",
|
|
913
914
|
actionItems: "عناصر العمل",
|
|
@@ -323,8 +323,7 @@ const messages = {
|
|
|
323
323
|
unassigned: "Nicht zugewiesen",
|
|
324
324
|
them: "Ihnen",
|
|
325
325
|
me: "Mich",
|
|
326
|
-
regeneratingNotes:
|
|
327
|
-
"Notizen neu generieren – Ihre eigenen Notizen bleiben erhalten",
|
|
326
|
+
regeneratingNotes: "Zusammenfassung wird neu generiert",
|
|
328
327
|
meetingRemoved: "Besprechung entfernt",
|
|
329
328
|
couldNotRemoveMeeting: "Das Meeting konnte nicht entfernt werden",
|
|
330
329
|
couldNotLoadMeeting: "Dieses Meeting konnte nicht geladen werden.",
|
|
@@ -332,8 +331,8 @@ const messages = {
|
|
|
332
331
|
couldNotCopyTranscript: "Das Transkript konnte nicht kopiert werden",
|
|
333
332
|
allMeetings: "Alle Treffen",
|
|
334
333
|
live: "Übersetzt: Live",
|
|
335
|
-
generatingNotesInline: "
|
|
336
|
-
regenerateNotes: "
|
|
334
|
+
generatingNotesInline: "Zusammenfassung wird erstellt…",
|
|
335
|
+
regenerateNotes: "Zusammenfassung neu generieren",
|
|
337
336
|
share: "Aktie",
|
|
338
337
|
meetingOptions: "Besprechungsmöglichkeiten",
|
|
339
338
|
removeMeeting: "Besprechung entfernen",
|
|
@@ -347,12 +346,13 @@ const messages = {
|
|
|
347
346
|
"Um Notizen zu starten, öffnen Sie Clips Desktop über die Menüleiste und wählen Sie Start Meeting Notes, oder klicken Sie auf Start notes, wenn die Erinnerung erscheint. Clips erfasst Mikrofon und Systemaudio und schreibt das Transkript hier.",
|
|
348
347
|
getDesktopApp: "Holen Sie sich die Desktop-App",
|
|
349
348
|
generateNotesFailed:
|
|
350
|
-
"
|
|
349
|
+
"Zusammenfassung konnte nicht generiert werden. Versuchen Sie es erneut.",
|
|
351
350
|
attendee_one: "{{count}}-Teilnehmer",
|
|
352
351
|
attendee_other: "{{count}}-Teilnehmer",
|
|
353
352
|
joinCall: "Nehmen Sie am Anruf teil",
|
|
354
353
|
myNotes: "Meine Notizen",
|
|
355
354
|
aiNotes: "KI-Notizen",
|
|
355
|
+
summary: "Zusammenfassung",
|
|
356
356
|
actionItems: "Aktionselemente",
|
|
357
357
|
working: "Arbeiten…",
|
|
358
358
|
noActionItems:
|
|
@@ -933,7 +933,7 @@ Alle sichtbaren Änderungen für Clips-Nutzer werden hier dokumentiert. Du kanns
|
|
|
933
933
|
unavailable: "Dieses Meeting ist privat oder nicht mehr verfügbar.",
|
|
934
934
|
tryClips: "Clips ausprobieren",
|
|
935
935
|
attendees: "{{count}} Teilnehmer",
|
|
936
|
-
noAiNotes: "Für dieses Meeting
|
|
936
|
+
noAiNotes: "Für dieses Meeting wurde noch keine Zusammenfassung generiert.",
|
|
937
937
|
summary: "Zusammenfassung",
|
|
938
938
|
keyPoints: "Kernpunkte",
|
|
939
939
|
actionItems: "Aufgaben",
|
|
@@ -309,7 +309,7 @@ const messages = {
|
|
|
309
309
|
unassigned: "Unassigned",
|
|
310
310
|
them: "Them",
|
|
311
311
|
me: "Me",
|
|
312
|
-
regeneratingNotes: "Regenerating
|
|
312
|
+
regeneratingNotes: "Regenerating summary",
|
|
313
313
|
meetingRemoved: "Meeting removed",
|
|
314
314
|
couldNotRemoveMeeting: "Couldn't remove meeting",
|
|
315
315
|
couldNotLoadMeeting: "Couldn't load this meeting.",
|
|
@@ -317,8 +317,8 @@ const messages = {
|
|
|
317
317
|
couldNotCopyTranscript: "Couldn't copy transcript",
|
|
318
318
|
allMeetings: "All meetings",
|
|
319
319
|
live: "Live",
|
|
320
|
-
generatingNotesInline: "Generating
|
|
321
|
-
regenerateNotes: "Regenerate
|
|
320
|
+
generatingNotesInline: "Generating summary…",
|
|
321
|
+
regenerateNotes: "Regenerate summary",
|
|
322
322
|
share: "Share",
|
|
323
323
|
meetingOptions: "Meeting options",
|
|
324
324
|
removeMeeting: "Remove meeting",
|
|
@@ -331,12 +331,13 @@ const messages = {
|
|
|
331
331
|
desktopHint:
|
|
332
332
|
"To start notes, open Clips Desktop from the menu bar and choose Start Meeting Notes, or click Start notes when the reminder appears. Clips captures mic + system audio and writes the transcript here.",
|
|
333
333
|
getDesktopApp: "Get desktop app",
|
|
334
|
-
generateNotesFailed: "Couldn't generate
|
|
334
|
+
generateNotesFailed: "Couldn't generate summary. Try again.",
|
|
335
335
|
attendee_one: "{{count}} attendee",
|
|
336
336
|
attendee_other: "{{count}} attendees",
|
|
337
337
|
joinCall: "Join call",
|
|
338
338
|
myNotes: "My notes",
|
|
339
339
|
aiNotes: "AI notes",
|
|
340
|
+
summary: "Summary",
|
|
340
341
|
actionItems: "Action items",
|
|
341
342
|
working: "Working…",
|
|
342
343
|
noActionItems:
|
|
@@ -902,7 +903,7 @@ All notable user-facing changes to Clips are documented here. Open it any time f
|
|
|
902
903
|
unavailable: "This meeting is private or no longer available.",
|
|
903
904
|
tryClips: "Try Clips",
|
|
904
905
|
attendees: "{{count}} attendees",
|
|
905
|
-
noAiNotes: "
|
|
906
|
+
noAiNotes: "A summary hasn't been generated yet for this meeting.",
|
|
906
907
|
summary: "Summary",
|
|
907
908
|
keyPoints: "Key points",
|
|
908
909
|
actionItems: "Action items",
|