@agent-native/core 0.103.0 → 0.104.0
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 +36 -0
- package/corpus/core/package.json +9 -2
- package/corpus/core/src/agent/engine/credential-errors.ts +2 -2
- package/corpus/core/src/agent/production-agent.ts +30 -0
- package/corpus/core/src/agent/run-store.ts +12 -2
- package/corpus/core/src/cli/create.ts +1 -0
- package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +30 -11
- package/corpus/core/src/cli/templates-meta.ts +4 -3
- package/corpus/core/src/client/AgentAskPopover.tsx +89 -0
- package/corpus/core/src/client/AgentChatHome.tsx +4 -0
- package/corpus/core/src/client/AgentPanel.tsx +321 -223
- package/corpus/core/src/client/AssistantChat.tsx +6 -10
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +53 -372
- package/corpus/core/src/client/agent-chat-adapter.ts +13 -1
- package/corpus/core/src/client/agent-page/AgentContextTab.tsx +133 -149
- package/corpus/core/src/client/agent-page/AgentEmptyState.tsx +44 -0
- package/corpus/core/src/client/agent-page/AgentJobsTab.tsx +153 -82
- package/corpus/core/src/client/agent-page/AgentTabFrame.tsx +39 -0
- package/corpus/core/src/client/agent-page/AgentTabsPage.tsx +368 -356
- package/corpus/core/src/client/agent-page/types.ts +1 -1
- package/corpus/core/src/client/analytics.ts +51 -5
- package/corpus/core/src/client/chat/run-recovery.tsx +12 -4
- package/corpus/core/src/client/composer/PromptComposer.tsx +5 -15
- package/corpus/core/src/client/composer/TiptapComposer.tsx +32 -3
- package/corpus/core/src/client/dynamic-suggestions.ts +3 -3
- package/corpus/core/src/client/index.ts +16 -1
- package/corpus/core/src/client/resources/ResourceTree.tsx +249 -38
- package/corpus/core/src/client/resources/ResourcesPanel.tsx +307 -140
- package/corpus/core/src/client/session-replay.ts +158 -5
- package/corpus/core/src/client/settings/AutomationsSection.tsx +30 -10
- package/corpus/core/src/client/settings/SettingsPanel.tsx +3 -2
- package/corpus/core/src/client/settings/SettingsTabsPage.tsx +2 -0
- package/corpus/core/src/client/settings/agent-settings-search.ts +2 -2
- package/corpus/core/src/client/use-chat-threads.ts +2 -0
- package/corpus/core/src/connections/catalog.ts +49 -7
- package/corpus/core/src/db/index.ts +6 -1
- package/corpus/core/src/extensions/actions.ts +106 -16
- package/corpus/core/src/extensions/content-patch.ts +22 -0
- package/corpus/core/src/extensions/routes.ts +18 -0
- package/corpus/core/src/extensions/store.ts +8 -0
- package/corpus/core/src/index.ts +3 -0
- package/corpus/core/src/ingestion/docx.ts +158 -0
- package/corpus/core/src/ingestion/figma-node-to-html.ts +1860 -0
- package/corpus/core/src/ingestion/figma.ts +548 -0
- package/corpus/core/src/ingestion/index.ts +107 -0
- package/corpus/core/src/ingestion/media.ts +264 -0
- package/corpus/core/src/ingestion/notion.ts +121 -0
- package/corpus/core/src/ingestion/office.ts +214 -0
- package/corpus/core/src/ingestion/orchestration.ts +160 -0
- package/corpus/core/src/ingestion/pptx.ts +333 -0
- package/corpus/core/src/ingestion/selection.ts +81 -0
- package/corpus/core/src/ingestion/website.ts +151 -0
- package/corpus/core/src/integrations/plugin.ts +45 -37
- package/corpus/core/src/localization/default-messages.ts +35 -12
- package/corpus/core/src/observability/hosted-model-experiment.ts +118 -0
- package/corpus/core/src/observability/traces.ts +5 -3
- package/corpus/core/src/provider-api/index.ts +452 -8
- package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +18 -1
- package/corpus/core/src/search-utils/index.ts +112 -0
- package/corpus/core/src/secrets/register-framework-secrets.ts +61 -0
- package/corpus/core/src/server/action-discovery.ts +33 -8
- package/corpus/core/src/server/agent-chat/framework-prompts.ts +2 -2
- package/corpus/core/src/server/agent-chat/prompt-resources.ts +144 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +6 -0
- package/corpus/core/src/server/core-routes-plugin.ts +12 -0
- package/corpus/core/src/server/index.ts +30 -0
- package/corpus/core/src/server/workspace-provider-oauth.ts +583 -0
- package/corpus/core/src/styles/agent-native.css +9 -0
- package/corpus/core/src/templates/default/app/i18n/en-US.ts +3 -3
- package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +14 -5
- package/corpus/core/src/templates/workspace-root/.env.example +12 -0
- package/corpus/core/src/vite/client.ts +2 -0
- package/corpus/core/src/workspace-connections/index.ts +6 -0
- package/corpus/core/src/workspace-connections/lifecycle.ts +43 -0
- package/corpus/core/src/workspace-connections/store.ts +16 -0
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +46 -3
- package/corpus/templates/analytics/AGENTS.md +9 -0
- package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +120 -6
- package/corpus/templates/analytics/actions/mutate-dashboard.ts +92 -30
- package/corpus/templates/analytics/actions/update-dashboard.ts +5 -5
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +313 -220
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +2 -2
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +9 -6
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +90 -64
- package/corpus/templates/analytics/app/i18n-data.ts +3 -3
- package/corpus/templates/analytics/app/lib/dashboard-list-loading.ts +25 -0
- package/corpus/templates/analytics/app/lib/item-popularity.ts +13 -4
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/pivot.ts +8 -3
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +1 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +15 -3
- package/corpus/templates/analytics/changelog/2026-07-16-dashboard-filter-defaults-can-now-be-changed-reliably-withou.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-16-dashboard-lists-load-in-one-stable-order-without-popping-bet.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-16-fixed-dashboard-filter-dropdown-text-alignment.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-16-recurring-signed-in-users-can-now-be-viewed-as-weekly-bars-b.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-16-the-analytics-agent-can-now-duplicate-a-chart-and-place-the-.md +6 -0
- package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +41 -1
- package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +1 -1
- package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +47 -1
- package/corpus/templates/analytics/server/lib/session-replay.ts +68 -0
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +1 -0
- package/corpus/templates/analytics/server/routes/sessions/lookup.get.ts +47 -0
- package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +16 -9
- package/corpus/templates/assets/.agents/skills/creative-context/SKILL.md +86 -0
- package/corpus/templates/assets/AGENTS.md +10 -0
- package/corpus/templates/assets/actions/create-generation-session.ts +59 -1
- package/corpus/templates/assets/actions/edit-image.ts +2 -0
- package/corpus/templates/assets/actions/generate-asset.ts +52 -0
- package/corpus/templates/assets/actions/generate-image-batch.ts +55 -0
- package/corpus/templates/assets/actions/generate-image.ts +219 -1
- package/corpus/templates/assets/actions/open-asset-picker.ts +14 -0
- package/corpus/templates/assets/actions/refine-image.ts +3 -0
- package/corpus/templates/assets/actions/restyle-image.ts +2 -0
- package/corpus/templates/assets/agent-native.app-skill.json +4 -0
- package/corpus/templates/assets/app/components/layout/Layout.tsx +2 -0
- package/corpus/templates/assets/app/i18n/zh-TW.ts +3 -0
- package/corpus/templates/assets/app/i18n-data.ts +29 -13
- package/corpus/templates/assets/app/routes/agent.tsx +7 -1
- package/corpus/templates/assets/app/routes/library.tsx +9 -0
- package/corpus/templates/assets/app/routes/settings.tsx +3 -0
- package/corpus/templates/assets/changelog/2026-07-16-creative-context-library.md +6 -0
- package/corpus/templates/assets/package.json +1 -0
- package/corpus/templates/assets/server/lib/image-processing.ts +1 -22
- package/corpus/templates/assets/server/plugins/creative-context.ts +205 -0
- package/corpus/templates/brain/app/i18n-data.ts +3 -3
- package/corpus/templates/brain/app/lib/brain.ts +1 -1
- package/corpus/templates/brain/server/lib/search.ts +17 -67
- package/corpus/templates/calendar/app/i18n-data.ts +3 -3
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +19 -18
- package/corpus/templates/chat/app/i18n/en-US.ts +3 -3
- package/corpus/templates/chat/app/lib/agent-page.tsx +10 -1
- package/corpus/templates/clips/.agents/skills/meetings/SKILL.md +1 -1
- package/corpus/templates/clips/AGENTS.md +4 -0
- package/corpus/templates/clips/actions/cleanup-transcript.ts +35 -4
- package/corpus/templates/clips/actions/create-meeting.ts +6 -2
- package/corpus/templates/clips/actions/create-organization.ts +3 -2
- package/corpus/templates/clips/actions/create-recording.ts +4 -1
- package/corpus/templates/clips/actions/finalize-recording.ts +44 -7
- package/corpus/templates/clips/actions/import-loom-recording.ts +4 -1
- package/corpus/templates/clips/actions/lib/create-recording-schema.ts +2 -2
- package/corpus/templates/clips/actions/list-meetings.ts +23 -5
- package/corpus/templates/clips/actions/list-organization-state.ts +1 -1
- package/corpus/templates/clips/actions/remove-silences.ts +10 -1
- package/corpus/templates/clips/actions/request-transcript.ts +53 -11
- package/corpus/templates/clips/actions/search-recordings-utils.ts +7 -0
- package/corpus/templates/clips/actions/search-recordings.ts +5 -8
- package/corpus/templates/clips/actions/set-organization-branding.ts +2 -2
- package/corpus/templates/clips/actions/stitch-recordings.ts +10 -5
- package/corpus/templates/clips/actions/update-ai-request-status.ts +38 -0
- package/corpus/templates/clips/app/components/editor/editor-layout.tsx +3 -4
- package/corpus/templates/clips/app/components/editor/editor-selection.ts +19 -0
- package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +10 -10
- package/corpus/templates/clips/app/components/library/bulk-action-toolbar.tsx +1 -2
- package/corpus/templates/clips/app/components/library/library-grid.tsx +101 -93
- package/corpus/templates/clips/app/components/player/video-player.tsx +11 -0
- package/corpus/templates/clips/app/components/workspace/branding-editor.tsx +53 -1
- package/corpus/templates/clips/app/i18n/ar-SA.ts +7 -1
- package/corpus/templates/clips/app/i18n/de-DE.ts +7 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +10 -4
- package/corpus/templates/clips/app/i18n/es-ES.ts +7 -1
- package/corpus/templates/clips/app/i18n/fr-FR.ts +7 -1
- package/corpus/templates/clips/app/i18n/hi-IN.ts +7 -1
- package/corpus/templates/clips/app/i18n/ja-JP.ts +7 -1
- package/corpus/templates/clips/app/i18n/ko-KR.ts +7 -1
- package/corpus/templates/clips/app/i18n/pt-BR.ts +7 -1
- package/corpus/templates/clips/app/i18n/zh-CN.ts +6 -1
- package/corpus/templates/clips/app/i18n/zh-TW.ts +6 -1
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +5 -9
- package/corpus/templates/clips/app/routes/_app.settings.organization.tsx +6 -2
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +129 -27
- package/corpus/templates/clips/app/routes/record.tsx +23 -2
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +6 -2
- package/corpus/templates/clips/changelog/2026-07-16-authorized-viewers-can-open-shared-private-clips-without-a-m.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-camera-bubble-hover-controls-appear-above-the-face.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-chrome-extension-recovers-stale-recorder-state.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-clips-agent-chat-no-longer-shows-a-separate-workspace-header.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-clips-search-now-matches-recording-content-without-requiring.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-declined-meetings-no-longer-show-desktop-reminders.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-failed-desktop-saves-now-show-their-local-recovery-copy.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-long-desktop-clips-now-preserve-complete-playback-synced-aud.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-long-recording-lists-keep-stitch-and-library-actions-visible.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-organization-admins-can-choose-new-recording-visibility.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-remove-silences-now-shows-queued-active-completed-and-failed.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-settings-no-longer-repeats-the-builder-connection-status-in-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-16-transcripts-now-appear-from-native-browser-speech-sooner-wit.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
- package/corpus/templates/clips/chrome-extension/src/background.ts +73 -1
- package/corpus/templates/clips/chrome-extension/src/native-recording-state.ts +32 -0
- package/corpus/templates/clips/chrome-extension/src/native-transcription.ts +248 -0
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +106 -0
- package/corpus/templates/clips/desktop/src/app.tsx +66 -28
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +335 -285
- package/corpus/templates/clips/desktop/src/lib/single-flight.ts +7 -0
- package/corpus/templates/clips/desktop/src/lib/upload-verification.ts +51 -0
- package/corpus/templates/clips/desktop/src/overlays/bubble.tsx +2 -2
- package/corpus/templates/clips/desktop/src/overlays/finalizing.tsx +10 -2
- package/corpus/templates/clips/desktop/src/styles.css +13 -11
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +8 -9
- package/corpus/templates/clips/desktop/src-tauri/src/meetings_watcher.rs +1 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +88 -13
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/live_upload.rs +13 -2
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +241 -6
- package/corpus/templates/clips/server/db/schema.ts +2 -2
- package/corpus/templates/clips/server/lib/builder-media-compression.ts +64 -67
- package/corpus/templates/clips/server/lib/calendar-event-classification.ts +19 -0
- package/corpus/templates/clips/server/lib/google-calendar-client.ts +1 -0
- package/corpus/templates/clips/server/lib/recordings.ts +40 -1
- package/corpus/templates/clips/server/plugins/agent-chat.ts +1 -0
- package/corpus/templates/clips/server/plugins/db.ts +2 -2
- package/corpus/templates/clips/server/routes/api/auth/google-calendar.get.ts +1 -1
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +14 -5
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +51 -1
- package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +1 -64
- package/corpus/templates/clips/shared/media-worker-contract.ts +32 -15
- package/corpus/templates/content/.agents/skills/content/SKILL.md +16 -0
- package/corpus/templates/content/.agents/skills/creative-context/SKILL.md +85 -0
- package/corpus/templates/content/.agents/skills/notion-integration/SKILL.md +8 -0
- package/corpus/templates/content/AGENTS.md +9 -0
- package/corpus/templates/content/actions/create-document.ts +94 -0
- package/corpus/templates/content/actions/edit-document.ts +144 -4
- package/corpus/templates/content/actions/update-document.ts +138 -0
- package/corpus/templates/content/agent-native.app-skill.json +4 -0
- package/corpus/templates/content/app/components/layout/Layout.tsx +2 -0
- package/corpus/templates/content/app/i18n/zh-TW.ts +3 -0
- package/corpus/templates/content/app/i18n-data.ts +13 -4
- package/corpus/templates/content/app/routes/_app.agent.tsx +2 -1
- package/corpus/templates/content/app/routes/_app.settings.tsx +3 -0
- package/corpus/templates/content/changelog/2026-07-16-creative-context-library.md +6 -0
- package/corpus/templates/content/package.json +1 -0
- package/corpus/templates/content/server/plugins/creative-context.ts +31 -0
- package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +116 -0
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +16 -0
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +8 -0
- package/corpus/templates/design/AGENTS.md +6 -0
- package/corpus/templates/design/actions/clone-creative-context-design.ts +176 -0
- package/corpus/templates/design/actions/edit-design.ts +128 -0
- package/corpus/templates/design/actions/generate-design.ts +278 -14
- package/corpus/templates/design/actions/generate-screens.ts +42 -1
- package/corpus/templates/design/agent-native.app-skill.json +4 -0
- package/corpus/templates/design/app/components/layout/Layout.tsx +7 -3
- package/corpus/templates/design/app/i18n/zh-TW.ts +3 -0
- package/corpus/templates/design/app/i18n-data.ts +10 -4
- package/corpus/templates/design/app/routes/agent.tsx +2 -1
- package/corpus/templates/design/app/routes/settings.tsx +3 -0
- package/corpus/templates/design/changelog/2026-07-16-creative-context-library.md +6 -0
- package/corpus/templates/design/changelog/2026-07-16-design-agent-chat-no-longer-shows-a-separate-workspace-header.md +6 -0
- package/corpus/templates/design/package.json +1 -0
- package/corpus/templates/design/server/lib/figma-design-context.ts +5 -335
- package/corpus/templates/design/server/lib/figma-node-to-html.ts +1 -1859
- package/corpus/templates/design/server/lib/import-design-files.ts +6 -8
- package/corpus/templates/design/server/plugins/creative-context.ts +31 -0
- package/corpus/templates/design/shared/generation-session.ts +7 -0
- package/corpus/templates/dispatch/app/i18n-data.ts +3 -3
- package/corpus/templates/forms/app/i18n/en-US.ts +3 -3
- package/corpus/templates/macros/app/i18n/en-US.ts +3 -3
- package/corpus/templates/mail/app/components/email/EmailThread.tsx +35 -5
- package/corpus/templates/mail/app/i18n/en-US.ts +3 -3
- package/corpus/templates/mail/changelog/2026-07-16-mail-previews-now-expand-to-show-the-full-message-without-an.md +6 -0
- package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +30 -11
- package/corpus/templates/plan/AGENTS.md +21 -1
- package/corpus/templates/plan/actions/get-visual-plan.ts +1 -1
- package/corpus/templates/plan/actions/patch-visual-plan-source.ts +161 -0
- package/corpus/templates/plan/actions/read-visual-plan-source.ts +1 -1
- package/corpus/templates/plan/actions/update-visual-plan.ts +126 -10
- package/corpus/templates/plan/app/hooks/use-plans.ts +2 -0
- package/corpus/templates/plan/app/i18n/en-US.ts +3 -3
- package/corpus/templates/plan/app/pages/PlansPage.tsx +65 -62
- package/corpus/templates/plan/changelog/2026-07-16-local-plan-previews-now-load-annotations-containing-html-lik.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-16-plan-agents-now-prevent-stale-edits-from-overwriting-newer-p.md +6 -0
- package/corpus/templates/plan/server/plan-mdx.ts +75 -2
- package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +21 -4
- package/corpus/templates/slides/.agents/skills/creative-context/SKILL.md +122 -0
- package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +11 -0
- package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +12 -3
- package/corpus/templates/slides/AGENTS.md +6 -0
- package/corpus/templates/slides/actions/add-slide.ts +230 -14
- package/corpus/templates/slides/actions/clone-context-slide.ts +302 -0
- package/corpus/templates/slides/actions/create-deck.ts +130 -0
- package/corpus/templates/slides/actions/extract-pdf.ts +6 -2
- package/corpus/templates/slides/actions/import-file.ts +5 -4
- package/corpus/templates/slides/actions/patch-deck.ts +200 -10
- package/corpus/templates/slides/actions/update-slide.ts +208 -15
- package/corpus/templates/slides/app/components/layout/Layout.tsx +2 -0
- package/corpus/templates/slides/app/components/visual-editor/CanvasCommentPins.tsx +16 -1
- package/corpus/templates/slides/app/i18n/ar-SA.ts +3 -0
- package/corpus/templates/slides/app/i18n/de-DE.ts +3 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +6 -3
- package/corpus/templates/slides/app/i18n/es-ES.ts +3 -0
- package/corpus/templates/slides/app/i18n/fr-FR.ts +3 -0
- package/corpus/templates/slides/app/i18n/hi-IN.ts +3 -0
- package/corpus/templates/slides/app/i18n/ja-JP.ts +3 -0
- package/corpus/templates/slides/app/i18n/ko-KR.ts +3 -0
- package/corpus/templates/slides/app/i18n/pt-BR.ts +3 -0
- package/corpus/templates/slides/app/i18n/zh-CN.ts +3 -0
- package/corpus/templates/slides/app/i18n/zh-TW.ts +3 -0
- package/corpus/templates/slides/app/lib/validate-native-slide-html.ts +176 -0
- package/corpus/templates/slides/app/routes/agent.tsx +7 -1
- package/corpus/templates/slides/app/routes/settings.tsx +3 -0
- package/corpus/templates/slides/changelog/2026-07-16-creative-context-library.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-16-google-slides-native-cloning.md +6 -0
- package/corpus/templates/slides/package.json +1 -0
- package/corpus/templates/slides/server/handlers/import/docx-parser.ts +4 -85
- package/corpus/templates/slides/server/handlers/import/pptx-parser.ts +7 -421
- package/corpus/templates/slides/server/plugins/creative-context.ts +166 -0
- package/dist/agent/engine/credential-errors.d.ts +1 -1
- package/dist/agent/engine/credential-errors.d.ts.map +1 -1
- package/dist/agent/engine/credential-errors.js +2 -2
- package/dist/agent/engine/credential-errors.js.map +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +25 -0
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +12 -2
- package/dist/agent/run-store.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +1 -0
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/skills-content/visual-plan-skill.d.ts +1 -1
- package/dist/cli/skills-content/visual-plan-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/visual-plan-skill.js +30 -11
- package/dist/cli/skills-content/visual-plan-skill.js.map +1 -1
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +4 -3
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/client/AgentAskPopover.d.ts +11 -0
- package/dist/client/AgentAskPopover.d.ts.map +1 -0
- package/dist/client/AgentAskPopover.js +30 -0
- package/dist/client/AgentAskPopover.js.map +1 -0
- package/dist/client/AgentChatHome.d.ts +1 -1
- package/dist/client/AgentChatHome.d.ts.map +1 -1
- package/dist/client/AgentChatHome.js +2 -2
- package/dist/client/AgentChatHome.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +9 -19
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +119 -80
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +4 -4
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts +3 -9
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +49 -189
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +12 -1
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/agent-page/AgentContextTab.d.ts.map +1 -1
- package/dist/client/agent-page/AgentContextTab.js +26 -28
- package/dist/client/agent-page/AgentContextTab.js.map +1 -1
- package/dist/client/agent-page/AgentEmptyState.d.ts +13 -0
- package/dist/client/agent-page/AgentEmptyState.d.ts.map +1 -0
- package/dist/client/agent-page/AgentEmptyState.js +6 -0
- package/dist/client/agent-page/AgentEmptyState.js.map +1 -0
- package/dist/client/agent-page/AgentJobsTab.d.ts +1 -1
- package/dist/client/agent-page/AgentJobsTab.d.ts.map +1 -1
- package/dist/client/agent-page/AgentJobsTab.js +90 -58
- package/dist/client/agent-page/AgentJobsTab.js.map +1 -1
- package/dist/client/agent-page/AgentTabFrame.d.ts +12 -0
- package/dist/client/agent-page/AgentTabFrame.d.ts.map +1 -0
- package/dist/client/agent-page/AgentTabFrame.js +7 -0
- package/dist/client/agent-page/AgentTabFrame.js.map +1 -0
- package/dist/client/agent-page/AgentTabsPage.d.ts +9 -1
- package/dist/client/agent-page/AgentTabsPage.d.ts.map +1 -1
- package/dist/client/agent-page/AgentTabsPage.js +135 -99
- package/dist/client/agent-page/AgentTabsPage.js.map +1 -1
- package/dist/client/agent-page/types.d.ts +1 -1
- package/dist/client/agent-page/types.d.ts.map +1 -1
- package/dist/client/agent-page/types.js.map +1 -1
- package/dist/client/analytics.d.ts +10 -3
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +37 -2
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/chat/run-recovery.d.ts.map +1 -1
- package/dist/client/chat/run-recovery.js +10 -3
- package/dist/client/chat/run-recovery.js.map +1 -1
- package/dist/client/composer/PromptComposer.d.ts.map +1 -1
- package/dist/client/composer/PromptComposer.js +2 -2
- package/dist/client/composer/PromptComposer.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +15 -3
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/dynamic-suggestions.js +3 -3
- package/dist/client/dynamic-suggestions.js.map +1 -1
- package/dist/client/index.d.ts +4 -3
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +3 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/resources/ResourceTree.d.ts +5 -1
- package/dist/client/resources/ResourceTree.d.ts.map +1 -1
- package/dist/client/resources/ResourceTree.js +74 -5
- package/dist/client/resources/ResourceTree.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.d.ts +11 -2
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +105 -31
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/session-replay.d.ts +28 -0
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +122 -8
- package/dist/client/session-replay.js.map +1 -1
- package/dist/client/settings/AutomationsSection.d.ts +3 -1
- package/dist/client/settings/AutomationsSection.d.ts.map +1 -1
- package/dist/client/settings/AutomationsSection.js +16 -6
- package/dist/client/settings/AutomationsSection.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +3 -3
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/SettingsTabsPage.d.ts +2 -0
- package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
- package/dist/client/settings/SettingsTabsPage.js.map +1 -1
- package/dist/client/settings/agent-settings-search.js +2 -2
- package/dist/client/settings/agent-settings-search.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts +2 -0
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/connections/catalog.d.ts +41 -7
- package/dist/connections/catalog.d.ts.map +1 -1
- package/dist/connections/catalog.js +40 -7
- package/dist/connections/catalog.js.map +1 -1
- package/dist/db/index.d.ts +2 -2
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +2 -2
- package/dist/db/index.js.map +1 -1
- package/dist/extensions/actions.d.ts.map +1 -1
- package/dist/extensions/actions.js +85 -15
- package/dist/extensions/actions.js.map +1 -1
- package/dist/extensions/content-patch.d.ts +4 -0
- package/dist/extensions/content-patch.d.ts.map +1 -1
- package/dist/extensions/content-patch.js +18 -0
- package/dist/extensions/content-patch.js.map +1 -1
- package/dist/extensions/routes.d.ts.map +1 -1
- package/dist/extensions/routes.js +14 -0
- package/dist/extensions/routes.js.map +1 -1
- package/dist/extensions/store.d.ts +1 -0
- package/dist/extensions/store.d.ts.map +1 -1
- package/dist/extensions/store.js +4 -1
- package/dist/extensions/store.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/ingestion/docx.d.ts +16 -0
- package/dist/ingestion/docx.d.ts.map +1 -0
- package/dist/ingestion/docx.js +129 -0
- package/dist/ingestion/docx.js.map +1 -0
- package/dist/ingestion/figma-node-to-html.d.ts +304 -0
- package/dist/ingestion/figma-node-to-html.d.ts.map +1 -0
- package/dist/ingestion/figma-node-to-html.js +1292 -0
- package/dist/ingestion/figma-node-to-html.js.map +1 -0
- package/dist/ingestion/figma.d.ts +115 -0
- package/dist/ingestion/figma.d.ts.map +1 -0
- package/dist/ingestion/figma.js +399 -0
- package/dist/ingestion/figma.js.map +1 -0
- package/dist/ingestion/index.d.ts +11 -0
- package/dist/ingestion/index.d.ts.map +1 -0
- package/dist/ingestion/index.js +11 -0
- package/dist/ingestion/index.js.map +1 -0
- package/dist/ingestion/media.d.ts +36 -0
- package/dist/ingestion/media.d.ts.map +1 -0
- package/dist/ingestion/media.js +178 -0
- package/dist/ingestion/media.js.map +1 -0
- package/dist/ingestion/notion.d.ts +12 -0
- package/dist/ingestion/notion.d.ts.map +1 -0
- package/dist/ingestion/notion.js +104 -0
- package/dist/ingestion/notion.js.map +1 -0
- package/dist/ingestion/office.d.ts +45 -0
- package/dist/ingestion/office.d.ts.map +1 -0
- package/dist/ingestion/office.js +141 -0
- package/dist/ingestion/office.js.map +1 -0
- package/dist/ingestion/orchestration.d.ts +52 -0
- package/dist/ingestion/orchestration.d.ts.map +1 -0
- package/dist/ingestion/orchestration.js +89 -0
- package/dist/ingestion/orchestration.js.map +1 -0
- package/dist/ingestion/pptx.d.ts +28 -0
- package/dist/ingestion/pptx.d.ts.map +1 -0
- package/dist/ingestion/pptx.js +255 -0
- package/dist/ingestion/pptx.js.map +1 -0
- package/dist/ingestion/selection.d.ts +20 -0
- package/dist/ingestion/selection.d.ts.map +1 -0
- package/dist/ingestion/selection.js +52 -0
- package/dist/ingestion/selection.js.map +1 -0
- package/dist/ingestion/website.d.ts +27 -0
- package/dist/ingestion/website.d.ts.map +1 -0
- package/dist/ingestion/website.js +100 -0
- package/dist/ingestion/website.js.map +1 -0
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +32 -27
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/localization/default-messages.d.ts +22 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +31 -9
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/observability/hosted-model-experiment.d.ts +39 -0
- package/dist/observability/hosted-model-experiment.d.ts.map +1 -0
- package/dist/observability/hosted-model-experiment.js +90 -0
- package/dist/observability/hosted-model-experiment.js.map +1 -0
- package/dist/observability/routes.d.ts +5 -5
- package/dist/observability/traces.d.ts.map +1 -1
- package/dist/observability/traces.js +5 -3
- package/dist/observability/traces.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/index.d.ts +35 -4
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/provider-api/index.js +339 -8
- package/dist/provider-api/index.js.map +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +18 -1
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/search-utils/index.d.ts +12 -0
- package/dist/search-utils/index.d.ts.map +1 -0
- package/dist/search-utils/index.js +95 -0
- package/dist/search-utils/index.js.map +1 -0
- package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
- package/dist/secrets/register-framework-secrets.js +57 -0
- package/dist/secrets/register-framework-secrets.js.map +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/action-discovery.d.ts +8 -0
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +26 -9
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/agent-chat/framework-prompts.js +2 -2
- package/dist/server/agent-chat/framework-prompts.js.map +1 -1
- package/dist/server/agent-chat/prompt-resources.d.ts +19 -0
- package/dist/server/agent-chat/prompt-resources.d.ts.map +1 -1
- package/dist/server/agent-chat/prompt-resources.js +95 -0
- package/dist/server/agent-chat/prompt-resources.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +7 -0
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +5 -0
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/index.d.ts +5 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +5 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/workspace-provider-oauth.d.ts +48 -0
- package/dist/server/workspace-provider-oauth.d.ts.map +1 -0
- package/dist/server/workspace-provider-oauth.js +415 -0
- package/dist/server/workspace-provider-oauth.js.map +1 -0
- package/dist/styles/agent-native.css +9 -0
- package/dist/templates/chat/app/i18n/en-US.ts +3 -3
- package/dist/templates/chat/app/lib/agent-page.tsx +10 -1
- package/dist/templates/default/app/i18n/en-US.ts +3 -3
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +14 -5
- package/dist/templates/workspace-root/.env.example +12 -0
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +2 -0
- package/dist/vite/client.js.map +1 -1
- package/dist/workspace-connections/index.d.ts +1 -0
- package/dist/workspace-connections/index.d.ts.map +1 -1
- package/dist/workspace-connections/index.js +1 -0
- package/dist/workspace-connections/index.js.map +1 -1
- package/dist/workspace-connections/lifecycle.d.ts +16 -0
- package/dist/workspace-connections/lifecycle.d.ts.map +1 -0
- package/dist/workspace-connections/lifecycle.js +14 -0
- package/dist/workspace-connections/lifecycle.js.map +1 -0
- package/dist/workspace-connections/store.d.ts.map +1 -1
- package/dist/workspace-connections/store.js +16 -0
- package/dist/workspace-connections/store.js.map +1 -1
- package/package.json +10 -3
- package/src/templates/chat/app/i18n/en-US.ts +3 -3
- package/src/templates/chat/app/lib/agent-page.spec.tsx +10 -1
- package/src/templates/chat/app/lib/agent-page.tsx +10 -1
- package/src/templates/default/app/i18n/en-US.ts +3 -3
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +14 -5
- package/src/templates/workspace-root/.env.example +12 -0
|
@@ -155,7 +155,21 @@ async function responseHasReadableMediaBytes(
|
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
|
|
158
|
+
function servedMediaSizeBytes(response: Response): number | null {
|
|
159
|
+
const contentRange = response.headers.get("content-range") ?? "";
|
|
160
|
+
const total = Number(contentRange.match(/\/(\d+)$/)?.[1]);
|
|
161
|
+
if (Number.isFinite(total) && total > 0) return total;
|
|
162
|
+
if (response.status === 200) {
|
|
163
|
+
const length = Number(response.headers.get("content-length"));
|
|
164
|
+
if (Number.isFinite(length) && length > 0) return length;
|
|
165
|
+
}
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async function verifyServedMediaUrl(
|
|
170
|
+
videoUrl: string,
|
|
171
|
+
expectedBytes: number,
|
|
172
|
+
): Promise<void> {
|
|
159
173
|
if (!shouldVerifyServedMediaUrl(videoUrl)) return;
|
|
160
174
|
|
|
161
175
|
let lastFailure = "media URL did not serve readable bytes";
|
|
@@ -176,11 +190,21 @@ async function verifyServedMediaUrl(videoUrl: string): Promise<void> {
|
|
|
176
190
|
signal: controller.signal,
|
|
177
191
|
});
|
|
178
192
|
const statusOk = response.status === 200 || response.status === 206;
|
|
179
|
-
if (statusOk
|
|
180
|
-
|
|
193
|
+
if (statusOk) {
|
|
194
|
+
const servedBytes = servedMediaSizeBytes(response);
|
|
195
|
+
if (servedBytes === null) {
|
|
196
|
+
lastFailure = "Stored media byte count could not be verified";
|
|
197
|
+
} else if (servedBytes !== expectedBytes) {
|
|
198
|
+
lastFailure = `Stored media byte count mismatch (${servedBytes} of ${expectedBytes} bytes)`;
|
|
199
|
+
} else if (await responseHasReadableMediaBytes(response)) {
|
|
200
|
+
return;
|
|
201
|
+
} else {
|
|
202
|
+
lastFailure = "media URL did not serve readable bytes";
|
|
203
|
+
}
|
|
204
|
+
} else {
|
|
205
|
+
lastFailure = `media URL returned HTTP ${response.status}`;
|
|
206
|
+
if (response.status < 500) break;
|
|
181
207
|
}
|
|
182
|
-
lastFailure = `media URL returned HTTP ${response.status}`;
|
|
183
|
-
if (response.status < 500) break;
|
|
184
208
|
} catch (err) {
|
|
185
209
|
lastFailure = err instanceof Error ? err.message : String(err);
|
|
186
210
|
} finally {
|
|
@@ -258,6 +282,7 @@ async function markRecordingReady(params: {
|
|
|
258
282
|
ownerEmail: string;
|
|
259
283
|
videoUrl: string;
|
|
260
284
|
videoSizeBytes: number;
|
|
285
|
+
sourceSizeBytes: number;
|
|
261
286
|
videoFormat: "webm" | "mp4";
|
|
262
287
|
finalDurationMs: number;
|
|
263
288
|
finalWidth: number;
|
|
@@ -275,6 +300,7 @@ async function markRecordingReady(params: {
|
|
|
275
300
|
ownerEmail,
|
|
276
301
|
videoUrl,
|
|
277
302
|
videoSizeBytes,
|
|
303
|
+
sourceSizeBytes,
|
|
278
304
|
videoFormat,
|
|
279
305
|
finalDurationMs,
|
|
280
306
|
finalWidth,
|
|
@@ -349,6 +375,7 @@ async function markRecordingReady(params: {
|
|
|
349
375
|
status: "failed" as const,
|
|
350
376
|
videoUrl,
|
|
351
377
|
videoSizeBytes,
|
|
378
|
+
sourceSizeBytes,
|
|
352
379
|
durationMs: finalDurationMs,
|
|
353
380
|
};
|
|
354
381
|
}
|
|
@@ -372,6 +399,9 @@ async function markRecordingReady(params: {
|
|
|
372
399
|
status: "ready",
|
|
373
400
|
progress: 100,
|
|
374
401
|
videoUrl,
|
|
402
|
+
videoSizeBytes,
|
|
403
|
+
sourceSizeBytes,
|
|
404
|
+
durationMs: finalDurationMs,
|
|
375
405
|
finishedAt: now,
|
|
376
406
|
});
|
|
377
407
|
await writeAppState("refresh-signal", { ts: Date.now() });
|
|
@@ -436,6 +466,7 @@ async function markRecordingReady(params: {
|
|
|
436
466
|
status: "ready" as const,
|
|
437
467
|
videoUrl,
|
|
438
468
|
videoSizeBytes,
|
|
469
|
+
sourceSizeBytes,
|
|
439
470
|
durationMs: finalDurationMs,
|
|
440
471
|
};
|
|
441
472
|
}
|
|
@@ -521,6 +552,7 @@ export default defineAction({
|
|
|
521
552
|
status: "ready" as const,
|
|
522
553
|
videoUrl: existing.videoUrl,
|
|
523
554
|
videoSizeBytes: existing.videoSizeBytes ?? 0,
|
|
555
|
+
sourceSizeBytes: existing.videoSizeBytes ?? 0,
|
|
524
556
|
durationMs: existing.durationMs ?? 0,
|
|
525
557
|
};
|
|
526
558
|
}
|
|
@@ -641,7 +673,10 @@ export default defineAction({
|
|
|
641
673
|
);
|
|
642
674
|
debugLog("[finalize] resumable upload completed", { id, videoUrl });
|
|
643
675
|
try {
|
|
644
|
-
await verifyServedMediaUrl(
|
|
676
|
+
await verifyServedMediaUrl(
|
|
677
|
+
videoUrl,
|
|
678
|
+
resumableSession.bytesUploaded,
|
|
679
|
+
);
|
|
645
680
|
} catch (err) {
|
|
646
681
|
const failureReason =
|
|
647
682
|
err instanceof Error ? err.message : String(err);
|
|
@@ -656,6 +691,7 @@ export default defineAction({
|
|
|
656
691
|
...readyParams,
|
|
657
692
|
videoUrl,
|
|
658
693
|
videoSizeBytes: resumableSession.bytesUploaded,
|
|
694
|
+
sourceSizeBytes: resumableSession.bytesUploaded,
|
|
659
695
|
// Streaming path forwards raw MediaRecorder bytes straight to the
|
|
660
696
|
// provider — no faststart/Cues rewrite happened. Repair in the
|
|
661
697
|
// background.
|
|
@@ -1162,7 +1198,7 @@ export default defineAction({
|
|
|
1162
1198
|
bytes: uploadData.byteLength,
|
|
1163
1199
|
});
|
|
1164
1200
|
try {
|
|
1165
|
-
await verifyServedMediaUrl(upload.url);
|
|
1201
|
+
await verifyServedMediaUrl(upload.url, uploadData.byteLength);
|
|
1166
1202
|
} catch (err) {
|
|
1167
1203
|
if (!requiresConfiguredVideoStorage()) {
|
|
1168
1204
|
// Local dev can keep scratch chunks so the user can retry after fixing
|
|
@@ -1185,6 +1221,7 @@ export default defineAction({
|
|
|
1185
1221
|
finalHasAudio: correctedHasAudio,
|
|
1186
1222
|
videoUrl: upload.url,
|
|
1187
1223
|
videoSizeBytes: uploadData.byteLength,
|
|
1224
|
+
sourceSizeBytes: assembled.byteLength,
|
|
1188
1225
|
seekableApplied,
|
|
1189
1226
|
});
|
|
1190
1227
|
if (result.status === "ready") {
|
|
@@ -11,6 +11,7 @@ import { getDb, schema } from "../server/db/index.js";
|
|
|
11
11
|
import { queueBuilderMediaCompression } from "../server/lib/builder-media-compression.js";
|
|
12
12
|
import {
|
|
13
13
|
getCurrentOwnerEmail,
|
|
14
|
+
getOrganizationDefaultVisibility,
|
|
14
15
|
nanoid,
|
|
15
16
|
ownerEmailMatches,
|
|
16
17
|
parseSpaceIds,
|
|
@@ -178,6 +179,8 @@ export default defineAction({
|
|
|
178
179
|
const { organizationId } = await requireOrganizationAccess(
|
|
179
180
|
existingRecording?.organizationId ?? args.organizationId,
|
|
180
181
|
);
|
|
182
|
+
const defaultVisibility =
|
|
183
|
+
await getOrganizationDefaultVisibility(organizationId);
|
|
181
184
|
|
|
182
185
|
const now = new Date().toISOString();
|
|
183
186
|
const id = existingRecording?.id ?? nanoid();
|
|
@@ -199,7 +202,7 @@ export default defineAction({
|
|
|
199
202
|
const height = boundedDimension(oembed.height ?? oembed.thumbnail_height);
|
|
200
203
|
const folderId = args.folderId ?? existingRecording?.folderId ?? null;
|
|
201
204
|
const visibility =
|
|
202
|
-
args.visibility ?? existingRecording?.visibility ??
|
|
205
|
+
args.visibility ?? existingRecording?.visibility ?? defaultVisibility;
|
|
203
206
|
const titleSource = args.title
|
|
204
207
|
? "manual"
|
|
205
208
|
: (existingRecording?.titleSource ?? "upload");
|
|
@@ -62,9 +62,9 @@ export const createRecordingSchema = z.object({
|
|
|
62
62
|
.describe("Height of the recording in pixels (may be 0 until finalized)"),
|
|
63
63
|
visibility: z
|
|
64
64
|
.enum(["private", "org", "public"])
|
|
65
|
-
.
|
|
65
|
+
.optional()
|
|
66
66
|
.describe(
|
|
67
|
-
"Initial share visibility for the recording
|
|
67
|
+
"Initial share visibility for the recording. When omitted, uses the organization default and falls back to public.",
|
|
68
68
|
),
|
|
69
69
|
mimeType: z
|
|
70
70
|
.string()
|
|
@@ -32,7 +32,10 @@ import {
|
|
|
32
32
|
import { z } from "zod";
|
|
33
33
|
|
|
34
34
|
import { getDb, schema } from "../server/db/index.js";
|
|
35
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
isDeclinedCalendarEvent,
|
|
37
|
+
isSoloCalendarEvent,
|
|
38
|
+
} from "../server/lib/calendar-event-classification.js";
|
|
36
39
|
import {
|
|
37
40
|
calendarEventToMeetingView,
|
|
38
41
|
eventEndIso,
|
|
@@ -89,6 +92,11 @@ export default defineAction({
|
|
|
89
92
|
.describe(
|
|
90
93
|
"Exclude calendar events with no active attendee besides the current user. Used by desktop meeting reminders.",
|
|
91
94
|
),
|
|
95
|
+
excludeDeclinedEvents: booleanParam
|
|
96
|
+
.default(false)
|
|
97
|
+
.describe(
|
|
98
|
+
"Exclude calendar events where the current user has declined. Used by desktop meeting reminders.",
|
|
99
|
+
),
|
|
92
100
|
}),
|
|
93
101
|
http: { method: "GET" },
|
|
94
102
|
run: async (args) => {
|
|
@@ -190,10 +198,10 @@ export default defineAction({
|
|
|
190
198
|
// event was emitted here — not merely because some other account returned
|
|
191
199
|
// data or errored.
|
|
192
200
|
const emittedLiveEventKeys = new Set<string>();
|
|
193
|
-
// Calendar events excluded from desktop reminders because they
|
|
194
|
-
//
|
|
195
|
-
//
|
|
196
|
-
//
|
|
201
|
+
// Calendar events excluded from desktop reminders because they are solo or
|
|
202
|
+
// declined by the current user. Keep the correlated persisted meeting ids
|
|
203
|
+
// here too, so materialized events cannot re-enter the reminder list
|
|
204
|
+
// through the fallback persisted-row merge.
|
|
197
205
|
const excludedLiveEventKeys = new Set<string>();
|
|
198
206
|
// Map a persisted meeting's `calendarEventId` (calendar_events.id) to the
|
|
199
207
|
// Google event externalId so we can match it against the emitted set.
|
|
@@ -277,6 +285,16 @@ export default defineAction({
|
|
|
277
285
|
if (!event.id || event.status === "cancelled") continue;
|
|
278
286
|
if (!isTimedCalendarEvent(event)) continue;
|
|
279
287
|
const cached = cachedByExternalId.get(event.id);
|
|
288
|
+
if (
|
|
289
|
+
args.excludeDeclinedEvents &&
|
|
290
|
+
isDeclinedCalendarEvent({ account, event, currentUserEmail })
|
|
291
|
+
) {
|
|
292
|
+
excludedLiveEventKeys.add(event.id);
|
|
293
|
+
if (cached?.meetingId) {
|
|
294
|
+
excludedLiveEventKeys.add(cached.meetingId);
|
|
295
|
+
}
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
280
298
|
if (
|
|
281
299
|
args.excludePersonalSoloEvents &&
|
|
282
300
|
isSoloCalendarEvent({ account, event, currentUserEmail })
|
|
@@ -143,7 +143,7 @@ export default defineAction({
|
|
|
143
143
|
name: org.name,
|
|
144
144
|
brandColor: settings?.brandColor ?? "#18181B",
|
|
145
145
|
brandLogoUrl: settings?.brandLogoUrl ?? null,
|
|
146
|
-
defaultVisibility: settings?.defaultVisibility ?? "
|
|
146
|
+
defaultVisibility: settings?.defaultVisibility ?? "public",
|
|
147
147
|
createdAt: Number(org.createdAt),
|
|
148
148
|
},
|
|
149
149
|
members,
|
|
@@ -56,9 +56,18 @@ export default defineAction({
|
|
|
56
56
|
`by analyzing the transcript segments (gaps between segment.endMs and the next segment.startMs). ` +
|
|
57
57
|
`For each gap > ${args.thresholdMs}ms, add a trim range covering the silence minus a 200ms ` +
|
|
58
58
|
`buffer on each side so speech isn't clipped. Then call ` +
|
|
59
|
-
`\`trim-recording --recordingId=${args.recordingId} --startMs=<start> --endMs=<end>\` once for each silence
|
|
59
|
+
`\`trim-recording --recordingId=${args.recordingId} --startMs=<start> --endMs=<end>\` once for each silence. ` +
|
|
60
|
+
`First call \`update-ai-request-status --recordingId=${args.recordingId} --kind=remove-silences --status=working\`. ` +
|
|
61
|
+
`After all trim calls finish, call the same action with --status=completed and a short result message. ` +
|
|
62
|
+
`If the work cannot finish, call it with --status=failed and explain why.`,
|
|
60
63
|
};
|
|
61
64
|
|
|
65
|
+
await writeAppState(`clips-ai-request-status-${args.recordingId}`, {
|
|
66
|
+
kind: "remove-silences",
|
|
67
|
+
status: "queued",
|
|
68
|
+
message: null,
|
|
69
|
+
updatedAt: new Date().toISOString(),
|
|
70
|
+
});
|
|
62
71
|
await writeAppState(`clips-ai-request-${args.recordingId}`, request as any);
|
|
63
72
|
await writeAppState("refresh-signal", { ts: Date.now() });
|
|
64
73
|
|
|
@@ -454,6 +454,18 @@ function fullTextSegmentJson(
|
|
|
454
454
|
return JSON.stringify(buildCaptionSegmentsFromText(text, durationMs));
|
|
455
455
|
}
|
|
456
456
|
|
|
457
|
+
export function isSafeTranscriptCleanupReplacement(
|
|
458
|
+
sourceText: string,
|
|
459
|
+
cleanedText: string,
|
|
460
|
+
): boolean {
|
|
461
|
+
const sourceLength = sourceText.trim().length;
|
|
462
|
+
const cleanedLength = cleanedText.trim().length;
|
|
463
|
+
if (!sourceLength || !cleanedLength) return false;
|
|
464
|
+
if (sourceLength < 200) return true;
|
|
465
|
+
const retention = cleanedLength / sourceLength;
|
|
466
|
+
return retention >= 0.6 && retention <= 1.25;
|
|
467
|
+
}
|
|
468
|
+
|
|
457
469
|
async function failEmptyProviderTranscript({
|
|
458
470
|
db,
|
|
459
471
|
recordingId,
|
|
@@ -719,19 +731,49 @@ async function cleanupNativeTranscript({
|
|
|
719
731
|
});
|
|
720
732
|
return { cleaned: false, provider: result.provider };
|
|
721
733
|
}
|
|
734
|
+
if (!isSafeTranscriptCleanupReplacement(sourceText, cleanedText)) {
|
|
735
|
+
await writeTranscriptCleanupState(recordingId, {
|
|
736
|
+
status: "failed",
|
|
737
|
+
provider: result.provider,
|
|
738
|
+
failureReason:
|
|
739
|
+
"Cleanup output was incomplete; the original transcript was kept.",
|
|
740
|
+
sourceChars: sourceText.length,
|
|
741
|
+
cleanedChars: cleanedText.length,
|
|
742
|
+
});
|
|
743
|
+
return { cleaned: false, provider: result.provider };
|
|
744
|
+
}
|
|
722
745
|
|
|
723
746
|
const now = new Date().toISOString();
|
|
724
747
|
const language = await resolveStoredLanguage(db, recordingId);
|
|
725
|
-
await
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
748
|
+
const updated = await db
|
|
749
|
+
.update(schema.recordingTranscripts)
|
|
750
|
+
.set({
|
|
751
|
+
ownerEmail,
|
|
752
|
+
status: "ready",
|
|
753
|
+
failureReason: null,
|
|
754
|
+
language,
|
|
755
|
+
segmentsJson: fullTextSegmentJson(cleanedText, durationMs),
|
|
756
|
+
fullText: cleanedText,
|
|
757
|
+
retryCount: 0,
|
|
758
|
+
updatedAt: now,
|
|
759
|
+
})
|
|
760
|
+
.where(
|
|
761
|
+
and(
|
|
762
|
+
eq(schema.recordingTranscripts.recordingId, recordingId),
|
|
763
|
+
eq(schema.recordingTranscripts.status, "ready"),
|
|
764
|
+
eq(schema.recordingTranscripts.fullText, sourceText),
|
|
765
|
+
),
|
|
766
|
+
)
|
|
767
|
+
.returning({ recordingId: schema.recordingTranscripts.recordingId });
|
|
768
|
+
if (!updated.length) {
|
|
769
|
+
await writeTranscriptCleanupState(recordingId, {
|
|
770
|
+
status: "failed",
|
|
771
|
+
provider: result.provider,
|
|
772
|
+
failureReason:
|
|
773
|
+
"Transcript changed during cleanup; the newer transcript was kept.",
|
|
774
|
+
});
|
|
775
|
+
return { cleaned: false, provider: result.provider };
|
|
776
|
+
}
|
|
735
777
|
await writeTranscriptCleanupState(recordingId, {
|
|
736
778
|
status: "ready",
|
|
737
779
|
provider: result.provider,
|
|
@@ -1060,7 +1102,7 @@ const requestTranscriptAction = defineAction({
|
|
|
1060
1102
|
|
|
1061
1103
|
const db = getDb();
|
|
1062
1104
|
|
|
1063
|
-
if (context?.caller === "tool") {
|
|
1105
|
+
if (context?.caller === "tool" || context?.caller === "frontend") {
|
|
1064
1106
|
const [existingTranscript] = await db
|
|
1065
1107
|
.select({
|
|
1066
1108
|
status: schema.recordingTranscripts.status,
|
|
@@ -5,6 +5,7 @@ import { and, eq, sql } from "drizzle-orm";
|
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
|
|
7
7
|
import { getDb, schema } from "../server/db/index.js";
|
|
8
|
+
import { buildCaseInsensitiveSearchPattern } from "./search-recordings-utils.js";
|
|
8
9
|
|
|
9
10
|
const SNIPPET_RADIUS = 80;
|
|
10
11
|
|
|
@@ -42,10 +43,6 @@ function recordingDeepLink(
|
|
|
42
43
|
});
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
function escapeLike(s: string): string {
|
|
46
|
-
return s.replace(/([\\%_])/g, "\\$1");
|
|
47
|
-
}
|
|
48
|
-
|
|
49
46
|
function buildSnippet(fullText: string, query: string): string | null {
|
|
50
47
|
if (!fullText || !query) return null;
|
|
51
48
|
const lower = fullText.toLowerCase();
|
|
@@ -113,7 +110,7 @@ export default defineAction({
|
|
|
113
110
|
http: { method: "GET" },
|
|
114
111
|
run: async (args) => {
|
|
115
112
|
const db = getDb();
|
|
116
|
-
const pattern =
|
|
113
|
+
const pattern = buildCaseInsensitiveSearchPattern(args.query);
|
|
117
114
|
|
|
118
115
|
// Title/description matches on the recordings table
|
|
119
116
|
const recMatches = await db
|
|
@@ -132,7 +129,7 @@ export default defineAction({
|
|
|
132
129
|
.where(
|
|
133
130
|
and(
|
|
134
131
|
accessFilter(schema.recordings, schema.recordingShares),
|
|
135
|
-
sql`(${schema.recordings.title} LIKE ${pattern} ESCAPE '\\' OR ${schema.recordings.description} LIKE ${pattern} ESCAPE '\\')`,
|
|
132
|
+
sql`(lower(${schema.recordings.title}) LIKE ${pattern} ESCAPE '\\' OR lower(${schema.recordings.description}) LIKE ${pattern} ESCAPE '\\')`,
|
|
136
133
|
),
|
|
137
134
|
)
|
|
138
135
|
.limit(args.limit);
|
|
@@ -162,7 +159,7 @@ export default defineAction({
|
|
|
162
159
|
.where(
|
|
163
160
|
and(
|
|
164
161
|
accessFilter(schema.recordings, schema.recordingShares),
|
|
165
|
-
sql
|
|
162
|
+
sql`lower(${schema.recordingTranscripts.fullText}) LIKE ${pattern} ESCAPE '\\'`,
|
|
166
163
|
),
|
|
167
164
|
)
|
|
168
165
|
.limit(args.limit);
|
|
@@ -190,7 +187,7 @@ export default defineAction({
|
|
|
190
187
|
.where(
|
|
191
188
|
and(
|
|
192
189
|
accessFilter(schema.recordings, schema.recordingShares),
|
|
193
|
-
sql
|
|
190
|
+
sql`lower(${schema.recordingComments.content}) LIKE ${pattern} ESCAPE '\\'`,
|
|
194
191
|
),
|
|
195
192
|
)
|
|
196
193
|
.limit(args.limit);
|
|
@@ -62,7 +62,7 @@ export default defineAction({
|
|
|
62
62
|
.values({
|
|
63
63
|
organizationId,
|
|
64
64
|
brandColor: "#18181B",
|
|
65
|
-
defaultVisibility: "
|
|
65
|
+
defaultVisibility: "public",
|
|
66
66
|
createdAt: nowIso,
|
|
67
67
|
updatedAt: nowIso,
|
|
68
68
|
})
|
|
@@ -120,7 +120,7 @@ export default defineAction({
|
|
|
120
120
|
name: updatedName,
|
|
121
121
|
brandColor: row?.brandColor ?? "#18181B",
|
|
122
122
|
brandLogoUrl: row?.brandLogoUrl ?? null,
|
|
123
|
-
defaultVisibility: row?.defaultVisibility ?? "
|
|
123
|
+
defaultVisibility: row?.defaultVisibility ?? "public",
|
|
124
124
|
updatedAt: row?.updatedAt ?? nowIso,
|
|
125
125
|
};
|
|
126
126
|
},
|
|
@@ -36,6 +36,7 @@ import { parseEdits, serializeEdits } from "../app/lib/timestamp-mapping.js";
|
|
|
36
36
|
import { getDb, schema } from "../server/db/index.js";
|
|
37
37
|
import {
|
|
38
38
|
getCurrentOwnerEmail,
|
|
39
|
+
getOrganizationDefaultVisibility,
|
|
39
40
|
nanoid,
|
|
40
41
|
ownerEmailMatches,
|
|
41
42
|
} from "../server/lib/recordings.js";
|
|
@@ -52,7 +53,9 @@ export default defineAction({
|
|
|
52
53
|
visibility: z
|
|
53
54
|
.enum(["private", "org", "public"])
|
|
54
55
|
.optional()
|
|
55
|
-
.describe(
|
|
56
|
+
.describe(
|
|
57
|
+
"Visibility for the new recording. When omitted, uses the organization default and falls back to public.",
|
|
58
|
+
),
|
|
56
59
|
videoUrl: z
|
|
57
60
|
.string()
|
|
58
61
|
.optional()
|
|
@@ -92,10 +95,10 @@ export default defineAction({
|
|
|
92
95
|
throw new Error("stitch-recordings needs at least 2 sourceRecordingIds");
|
|
93
96
|
}
|
|
94
97
|
|
|
95
|
-
// Stitch creates a brand-new recording owned by the caller
|
|
96
|
-
//
|
|
98
|
+
// Stitch creates a brand-new recording owned by the caller, so every
|
|
99
|
+
// source must be OWNED by the caller (not
|
|
97
100
|
// just editor-shared) — otherwise a user with editor access to a
|
|
98
|
-
// private/org clip could reshare it as a new
|
|
101
|
+
// private/org clip could reshare it as a new recording they own.
|
|
99
102
|
const sources = await db
|
|
100
103
|
.select()
|
|
101
104
|
.from(schema.recordings)
|
|
@@ -117,6 +120,8 @@ export default defineAction({
|
|
|
117
120
|
assertNativeRecordingMedia(source);
|
|
118
121
|
}
|
|
119
122
|
const organizationId = ordered[0].organizationId;
|
|
123
|
+
const defaultVisibility =
|
|
124
|
+
await getOrganizationDefaultVisibility(organizationId);
|
|
120
125
|
|
|
121
126
|
const totalDuration =
|
|
122
127
|
args.durationMs ??
|
|
@@ -152,7 +157,7 @@ export default defineAction({
|
|
|
152
157
|
hasCamera: ordered.some((r) => Boolean(r.hasCamera)),
|
|
153
158
|
editsJson: serializeEdits(edits),
|
|
154
159
|
ownerEmail,
|
|
155
|
-
visibility: args.visibility ??
|
|
160
|
+
visibility: args.visibility ?? defaultVisibility,
|
|
156
161
|
createdAt: now,
|
|
157
162
|
updatedAt: now,
|
|
158
163
|
// Reuse the first source's thumbnail so the new row has something to show immediately.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import { writeAppState } from "@agent-native/core/application-state";
|
|
3
|
+
import { assertAccess } from "@agent-native/core/sharing";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
|
|
6
|
+
const STATUS_KEY_PREFIX = "clips-ai-request-status-";
|
|
7
|
+
|
|
8
|
+
export default defineAction({
|
|
9
|
+
description:
|
|
10
|
+
"Report progress or completion for queued Clips AI work so the recording page can show its current status.",
|
|
11
|
+
schema: z.object({
|
|
12
|
+
recordingId: z.string().describe("Recording ID"),
|
|
13
|
+
kind: z.enum(["remove-silences"]).describe("Queued request kind"),
|
|
14
|
+
status: z
|
|
15
|
+
.enum(["working", "completed", "failed"])
|
|
16
|
+
.describe("Current request status"),
|
|
17
|
+
message: z
|
|
18
|
+
.string()
|
|
19
|
+
.trim()
|
|
20
|
+
.max(500)
|
|
21
|
+
.optional()
|
|
22
|
+
.describe("Optional short status detail"),
|
|
23
|
+
}),
|
|
24
|
+
run: async (args) => {
|
|
25
|
+
await assertAccess("recording", args.recordingId, "editor");
|
|
26
|
+
await writeAppState(`${STATUS_KEY_PREFIX}${args.recordingId}`, {
|
|
27
|
+
kind: args.kind,
|
|
28
|
+
status: args.status,
|
|
29
|
+
message: args.message || null,
|
|
30
|
+
updatedAt: new Date().toISOString(),
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
recordingId: args.recordingId,
|
|
34
|
+
kind: args.kind,
|
|
35
|
+
status: args.status,
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
});
|
|
@@ -70,6 +70,7 @@ import { cn } from "@/lib/utils";
|
|
|
70
70
|
import { computePeaks, type WaveformPeaks } from "@/lib/waveform-peaks";
|
|
71
71
|
|
|
72
72
|
import { ChaptersEditor } from "./chapters-editor";
|
|
73
|
+
import { defaultSelectionRange } from "./editor-selection";
|
|
73
74
|
import { EditorToolbar } from "./editor-toolbar";
|
|
74
75
|
import { StitchManager } from "./stitch-manager";
|
|
75
76
|
import { ThumbnailPicker } from "./thumbnail-picker";
|
|
@@ -604,10 +605,8 @@ export function EditorLayout({ recordingId, className }: EditorLayoutProps) {
|
|
|
604
605
|
}, [playheadMs, recordingId, selectionRange, split, trim, undo]);
|
|
605
606
|
|
|
606
607
|
// Default selection window so the TrimHandles have something to render.
|
|
607
|
-
const effectiveSelection =
|
|
608
|
-
|
|
609
|
-
endMs: durationMs || 1_000,
|
|
610
|
-
};
|
|
608
|
+
const effectiveSelection =
|
|
609
|
+
selectionRange ?? defaultSelectionRange(playheadMs, durationMs);
|
|
611
610
|
|
|
612
611
|
if (playerDataQuery.isLoading) {
|
|
613
612
|
return (
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const DEFAULT_SELECTION_WINDOW_MS = 1_000;
|
|
2
|
+
|
|
3
|
+
export function defaultSelectionRange(
|
|
4
|
+
playheadMs: number,
|
|
5
|
+
durationMs: number,
|
|
6
|
+
): { startMs: number; endMs: number } {
|
|
7
|
+
const clipDuration =
|
|
8
|
+
Number.isFinite(durationMs) && durationMs > 0
|
|
9
|
+
? durationMs
|
|
10
|
+
: DEFAULT_SELECTION_WINDOW_MS;
|
|
11
|
+
const playhead = Number.isFinite(playheadMs)
|
|
12
|
+
? Math.max(0, Math.min(clipDuration, playheadMs))
|
|
13
|
+
: 0;
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
startMs: Math.max(0, playhead - DEFAULT_SELECTION_WINDOW_MS),
|
|
17
|
+
endMs: Math.min(clipDuration, playhead + DEFAULT_SELECTION_WINDOW_MS),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -169,20 +169,20 @@ export function StitchManager({
|
|
|
169
169
|
|
|
170
170
|
return (
|
|
171
171
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
172
|
-
<DialogContent className="max-w-3xl">
|
|
173
|
-
<DialogHeader>
|
|
172
|
+
<DialogContent className="flex max-h-[min(760px,calc(100vh-32px))] max-w-3xl flex-col gap-0">
|
|
173
|
+
<DialogHeader className="shrink-0">
|
|
174
174
|
<DialogTitle className="flex items-center gap-2">
|
|
175
175
|
<IconPuzzle className="w-4 h-4 text-primary" />
|
|
176
176
|
{t("stitchManager.title")}
|
|
177
177
|
</DialogTitle>
|
|
178
178
|
</DialogHeader>
|
|
179
179
|
|
|
180
|
-
<div className="grid grid-cols-2 gap-3
|
|
181
|
-
<div className="flex flex-col
|
|
180
|
+
<div className="grid min-h-[320px] flex-1 grid-cols-2 gap-3">
|
|
181
|
+
<div className="flex min-h-0 min-w-0 flex-col rounded-md border">
|
|
182
182
|
<div className="px-3 py-2 text-xs font-medium border-b">
|
|
183
183
|
{t("navigation.library")}
|
|
184
184
|
</div>
|
|
185
|
-
<ScrollArea className="flex-1">
|
|
185
|
+
<ScrollArea className="min-h-0 flex-1">
|
|
186
186
|
{available.length === 0 ? (
|
|
187
187
|
<div className="p-3 text-xs text-muted-foreground">
|
|
188
188
|
{t("stitchManager.noOtherRecordings")}
|
|
@@ -214,7 +214,7 @@ export function StitchManager({
|
|
|
214
214
|
</ScrollArea>
|
|
215
215
|
</div>
|
|
216
216
|
|
|
217
|
-
<div className="flex flex-col
|
|
217
|
+
<div className="flex min-h-0 min-w-0 flex-col rounded-md border">
|
|
218
218
|
<div className="px-3 py-2 text-xs font-medium border-b flex items-center justify-between">
|
|
219
219
|
<span>{t("stitchManager.combineOrder")}</span>
|
|
220
220
|
<span className="text-muted-foreground">
|
|
@@ -222,7 +222,7 @@ export function StitchManager({
|
|
|
222
222
|
{formatMs(queue.reduce((s, r) => s + r.durationMs, 0))}
|
|
223
223
|
</span>
|
|
224
224
|
</div>
|
|
225
|
-
<ScrollArea className="flex-1">
|
|
225
|
+
<ScrollArea className="min-h-0 flex-1">
|
|
226
226
|
{queue.length === 0 ? (
|
|
227
227
|
<div className="p-3 text-xs text-muted-foreground">
|
|
228
228
|
{t("stitchManager.emptyQueue")}
|
|
@@ -263,7 +263,7 @@ export function StitchManager({
|
|
|
263
263
|
</div>
|
|
264
264
|
</div>
|
|
265
265
|
|
|
266
|
-
<div className="flex items-center gap-2">
|
|
266
|
+
<div className="flex shrink-0 items-center gap-2 pt-4">
|
|
267
267
|
<label className="text-xs text-muted-foreground">
|
|
268
268
|
{t("stitchManager.titleLabel")}
|
|
269
269
|
</label>
|
|
@@ -275,7 +275,7 @@ export function StitchManager({
|
|
|
275
275
|
</div>
|
|
276
276
|
|
|
277
277
|
{busy && (
|
|
278
|
-
<div className="
|
|
278
|
+
<div className="flex shrink-0 items-center gap-2 pt-3 text-xs text-muted-foreground">
|
|
279
279
|
<IconLoader2 className="w-4 h-4 animate-spin" />
|
|
280
280
|
{t("stitchManager.combining", {
|
|
281
281
|
progress: Math.round(progress * 100),
|
|
@@ -283,7 +283,7 @@ export function StitchManager({
|
|
|
283
283
|
</div>
|
|
284
284
|
)}
|
|
285
285
|
|
|
286
|
-
<DialogFooter>
|
|
286
|
+
<DialogFooter className="shrink-0 pt-4">
|
|
287
287
|
<Button variant="ghost" onClick={() => onOpenChange(false)}>
|
|
288
288
|
{t("common.cancel")}
|
|
289
289
|
</Button>
|
|
@@ -45,8 +45,7 @@ export function BulkActionToolbar({
|
|
|
45
45
|
return (
|
|
46
46
|
<div
|
|
47
47
|
className={cn(
|
|
48
|
-
"
|
|
49
|
-
"w-fit",
|
|
48
|
+
"flex w-fit max-w-full items-center gap-1 rounded-xl border border-border bg-popover px-3 py-2 shadow-lg",
|
|
50
49
|
)}
|
|
51
50
|
>
|
|
52
51
|
<span className="pe-2 text-xs font-medium text-foreground">
|