@agent-native/core 0.103.1 → 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 +30 -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/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/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/notifications/routes.d.ts +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/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/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/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/agent-engine-api-key-route.d.ts +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/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
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
shouldReconcilePersistedRecording,
|
|
3
|
+
type OffscreenRecordingState,
|
|
4
|
+
} from "./native-recording-state";
|
|
1
5
|
import { captureExtensionError, initExtensionSentry } from "./sentry";
|
|
2
6
|
|
|
3
7
|
initExtensionSentry("background");
|
|
@@ -174,6 +178,7 @@ type OffscreenStatusMessage = {
|
|
|
174
178
|
storageSetupRequired?: boolean;
|
|
175
179
|
savedToDisk?: boolean;
|
|
176
180
|
savedFilename?: string;
|
|
181
|
+
recordingStep?: string;
|
|
177
182
|
};
|
|
178
183
|
|
|
179
184
|
type ExtensionErrorMessage = {
|
|
@@ -1154,6 +1159,7 @@ async function startRecordingFromTab(args: {
|
|
|
1154
1159
|
settings: ExtensionSettings;
|
|
1155
1160
|
}) {
|
|
1156
1161
|
const { tab, settings } = args;
|
|
1162
|
+
await reconcilePersistedNativeRecording();
|
|
1157
1163
|
// The persisted value is authoritative (survives a worker suspension during
|
|
1158
1164
|
// arming); the in-memory var is only a same-tick fast path on top of it.
|
|
1159
1165
|
// Stale (past-TTL) or legacy-shaped guards are treated as absent — see
|
|
@@ -1311,7 +1317,6 @@ async function armRecording(args: {
|
|
|
1311
1317
|
hasCamera: cameraInvolved,
|
|
1312
1318
|
hasAudio:
|
|
1313
1319
|
settings.includeMicrophone || settings.captureSurface !== "camera",
|
|
1314
|
-
visibility: "public",
|
|
1315
1320
|
mimeType: "video/webm",
|
|
1316
1321
|
requestStreaming: true,
|
|
1317
1322
|
});
|
|
@@ -1382,6 +1387,7 @@ async function armRecording(args: {
|
|
|
1382
1387
|
hasCamera: cameraInvolved,
|
|
1383
1388
|
startDelayMs,
|
|
1384
1389
|
authToken,
|
|
1390
|
+
transcriptUrl: actionUrl(settings, "save-browser-transcript"),
|
|
1385
1391
|
});
|
|
1386
1392
|
} catch (err) {
|
|
1387
1393
|
console.error("[clips-bg] arm: BEGIN failed", err);
|
|
@@ -1548,6 +1554,10 @@ async function handleOverlayRestart() {
|
|
|
1548
1554
|
hasCamera: cameraInvolved,
|
|
1549
1555
|
startDelayMs: cameraInvolved ? 20000 : COUNTDOWN_SECONDS * 1000 + 1000,
|
|
1550
1556
|
authToken: restartAuthToken,
|
|
1557
|
+
transcriptUrl: actionUrl(
|
|
1558
|
+
settingsFromRecording(recording),
|
|
1559
|
+
"save-browser-transcript",
|
|
1560
|
+
),
|
|
1551
1561
|
});
|
|
1552
1562
|
} catch (err) {
|
|
1553
1563
|
// Re-arming failed: tear the countdown overlay back down and report the
|
|
@@ -1721,7 +1731,48 @@ async function clearNativeRecording(): Promise<void> {
|
|
|
1721
1731
|
await chrome.action.setBadgeText({ text: "" });
|
|
1722
1732
|
}
|
|
1723
1733
|
|
|
1734
|
+
async function reconcilePersistedNativeRecording(): Promise<void> {
|
|
1735
|
+
const recording = activeNativeRecording;
|
|
1736
|
+
if (!recording) return;
|
|
1737
|
+
if (recording.status === "error" || recording.status === "complete") return;
|
|
1738
|
+
|
|
1739
|
+
try {
|
|
1740
|
+
await ensureOffscreenDocument();
|
|
1741
|
+
const state = await sendOffscreenMessage<OffscreenRecordingState>({
|
|
1742
|
+
type: "CLIPS_OFFSCREEN_STATUS",
|
|
1743
|
+
});
|
|
1744
|
+
if (
|
|
1745
|
+
!shouldReconcilePersistedRecording(
|
|
1746
|
+
recording.status,
|
|
1747
|
+
recording.sessionId,
|
|
1748
|
+
state,
|
|
1749
|
+
)
|
|
1750
|
+
) {
|
|
1751
|
+
return;
|
|
1752
|
+
}
|
|
1753
|
+
} catch {
|
|
1754
|
+
// A transient wake-up failure must not discard a real recording.
|
|
1755
|
+
return;
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
console.warn(
|
|
1759
|
+
"[clips-bg] clearing persisted recording with no live offscreen session",
|
|
1760
|
+
recording.sessionId,
|
|
1761
|
+
);
|
|
1762
|
+
await deleteSession(recording.sessionId).catch((error) => {
|
|
1763
|
+
console.warn(
|
|
1764
|
+
"[clips-bg] stale recording cleanup could not detach tab",
|
|
1765
|
+
error,
|
|
1766
|
+
);
|
|
1767
|
+
});
|
|
1768
|
+
resetOverlay();
|
|
1769
|
+
await broadcastUnmount();
|
|
1770
|
+
broadcastOverlayState();
|
|
1771
|
+
await clearNativeRecording();
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1724
1774
|
async function handlePopupStatus() {
|
|
1775
|
+
await reconcilePersistedNativeRecording();
|
|
1725
1776
|
return {
|
|
1726
1777
|
ok: true,
|
|
1727
1778
|
activeRecording: activeNativeRecording,
|
|
@@ -2355,6 +2406,27 @@ async function dispatchRuntimeMessage(message: unknown): Promise<unknown> {
|
|
|
2355
2406
|
? status.savedFilename
|
|
2356
2407
|
: undefined;
|
|
2357
2408
|
}
|
|
2409
|
+
if (
|
|
2410
|
+
status.status === "error" &&
|
|
2411
|
+
status.recordingStep === "recorder-start"
|
|
2412
|
+
) {
|
|
2413
|
+
await deleteSession(activeNativeRecording.sessionId).catch((error) => {
|
|
2414
|
+
console.warn(
|
|
2415
|
+
"[clips-bg] failed recorder-start cleanup could not detach tab",
|
|
2416
|
+
error,
|
|
2417
|
+
);
|
|
2418
|
+
});
|
|
2419
|
+
await postAction(
|
|
2420
|
+
settingsFromRecording(activeNativeRecording),
|
|
2421
|
+
"trash-recording",
|
|
2422
|
+
{ id: activeNativeRecording.recordingId },
|
|
2423
|
+
).catch(() => undefined);
|
|
2424
|
+
resetOverlay();
|
|
2425
|
+
await broadcastUnmount();
|
|
2426
|
+
broadcastOverlayState();
|
|
2427
|
+
await clearNativeRecording();
|
|
2428
|
+
return { ok: true };
|
|
2429
|
+
}
|
|
2358
2430
|
await saveActiveNativeRecording();
|
|
2359
2431
|
// The offscreen recorder finished its pre-roll and actually started —
|
|
2360
2432
|
// advance from countdown to recording (the reliable phase flip).
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type NativeRecordingStateStatus =
|
|
2
|
+
| "recording"
|
|
3
|
+
| "paused"
|
|
4
|
+
| "stopping"
|
|
5
|
+
| "uploading"
|
|
6
|
+
| "complete"
|
|
7
|
+
| "error";
|
|
8
|
+
|
|
9
|
+
export type OffscreenRecordingState = {
|
|
10
|
+
activeSessionId?: string;
|
|
11
|
+
preparedSessionId?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function hasLiveOffscreenSession(
|
|
15
|
+
sessionId: string,
|
|
16
|
+
state: OffscreenRecordingState,
|
|
17
|
+
): boolean {
|
|
18
|
+
return (
|
|
19
|
+
state.activeSessionId === sessionId || state.preparedSessionId === sessionId
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function shouldReconcilePersistedRecording(
|
|
24
|
+
status: NativeRecordingStateStatus,
|
|
25
|
+
sessionId: string,
|
|
26
|
+
state: OffscreenRecordingState,
|
|
27
|
+
): boolean {
|
|
28
|
+
// Preserve terminal errors so the popup can explain an upload failure and
|
|
29
|
+
// offer the existing discard/re-upload path.
|
|
30
|
+
if (status === "error" || status === "complete") return false;
|
|
31
|
+
return !hasLiveOffscreenSession(sessionId, state);
|
|
32
|
+
}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
export interface NativeTranscriptResult {
|
|
2
|
+
text: string;
|
|
3
|
+
failureReason: string | null;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
interface SpeechRecognitionResultLike {
|
|
7
|
+
isFinal: boolean;
|
|
8
|
+
0?: { transcript?: string };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface SpeechRecognitionEventLike {
|
|
12
|
+
resultIndex: number;
|
|
13
|
+
results: ArrayLike<SpeechRecognitionResultLike>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface SpeechRecognitionErrorEventLike {
|
|
17
|
+
error?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface SpeechRecognitionLike {
|
|
21
|
+
continuous: boolean;
|
|
22
|
+
interimResults: boolean;
|
|
23
|
+
lang: string;
|
|
24
|
+
maxAlternatives: number;
|
|
25
|
+
onresult: ((event: SpeechRecognitionEventLike) => void) | null;
|
|
26
|
+
onerror: ((event: SpeechRecognitionErrorEventLike) => void) | null;
|
|
27
|
+
onend: (() => void) | null;
|
|
28
|
+
start: () => void;
|
|
29
|
+
stop: () => void;
|
|
30
|
+
abort: () => void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type SpeechRecognitionConstructor = new () => SpeechRecognitionLike;
|
|
34
|
+
|
|
35
|
+
export interface NativeTranscriptionCapture {
|
|
36
|
+
supported: boolean;
|
|
37
|
+
start(): void;
|
|
38
|
+
stop(): Promise<NativeTranscriptResult>;
|
|
39
|
+
cancel(): void;
|
|
40
|
+
pause(): void;
|
|
41
|
+
resume(): void;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const STOP_SETTLE_MS = 1_500;
|
|
45
|
+
const RESTART_DELAY_MS = 250;
|
|
46
|
+
|
|
47
|
+
function getSpeechRecognitionCtor(): SpeechRecognitionConstructor | null {
|
|
48
|
+
if (typeof window === "undefined") return null;
|
|
49
|
+
const scope = window as unknown as {
|
|
50
|
+
SpeechRecognition?: SpeechRecognitionConstructor;
|
|
51
|
+
webkitSpeechRecognition?: SpeechRecognitionConstructor;
|
|
52
|
+
};
|
|
53
|
+
return scope.SpeechRecognition ?? scope.webkitSpeechRecognition ?? null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function appendTranscript(current: string, next: string): string {
|
|
57
|
+
const cleanNext = next.trim();
|
|
58
|
+
if (!cleanNext) return current;
|
|
59
|
+
return current ? `${current} ${cleanNext}` : cleanNext;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function createNativeTranscriptionCapture(options?: {
|
|
63
|
+
enabled?: boolean;
|
|
64
|
+
lang?: string;
|
|
65
|
+
}): NativeTranscriptionCapture {
|
|
66
|
+
const Ctor = getSpeechRecognitionCtor();
|
|
67
|
+
const enabled = options?.enabled ?? true;
|
|
68
|
+
const language =
|
|
69
|
+
options?.lang ??
|
|
70
|
+
(typeof navigator !== "undefined" ? navigator.language : "en-US");
|
|
71
|
+
const unsupportedReason = !enabled
|
|
72
|
+
? "Native speech transcription requires microphone capture."
|
|
73
|
+
: !Ctor
|
|
74
|
+
? "Chrome Web Speech recognition is unavailable in this context."
|
|
75
|
+
: null;
|
|
76
|
+
|
|
77
|
+
let recognition: SpeechRecognitionLike | null = null;
|
|
78
|
+
let finalText = "";
|
|
79
|
+
let interimText = "";
|
|
80
|
+
let stopped = false;
|
|
81
|
+
let paused = false;
|
|
82
|
+
let disposed = false;
|
|
83
|
+
let failureReason = unsupportedReason;
|
|
84
|
+
let restartTimer: ReturnType<typeof setTimeout> | null = null;
|
|
85
|
+
let stopPromise: Promise<NativeTranscriptResult> | null = null;
|
|
86
|
+
let resolveStop: ((result: NativeTranscriptResult) => void) | null = null;
|
|
87
|
+
let stopTimer: ReturnType<typeof setTimeout> | null = null;
|
|
88
|
+
|
|
89
|
+
const result = (): NativeTranscriptResult => {
|
|
90
|
+
const text = appendTranscript(finalText, interimText).trim();
|
|
91
|
+
return {
|
|
92
|
+
text,
|
|
93
|
+
failureReason:
|
|
94
|
+
text.length > 0
|
|
95
|
+
? null
|
|
96
|
+
: failureReason ||
|
|
97
|
+
"Chrome Web Speech recognition returned no transcript.",
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const settleStop = (): void => {
|
|
102
|
+
if (!resolveStop) return;
|
|
103
|
+
if (stopTimer !== null) {
|
|
104
|
+
clearTimeout(stopTimer);
|
|
105
|
+
stopTimer = null;
|
|
106
|
+
}
|
|
107
|
+
const resolve = resolveStop;
|
|
108
|
+
resolveStop = null;
|
|
109
|
+
disposed = true;
|
|
110
|
+
recognition = null;
|
|
111
|
+
resolve(result());
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const scheduleRestart = (): void => {
|
|
115
|
+
if (restartTimer !== null) return;
|
|
116
|
+
restartTimer = setTimeout(() => {
|
|
117
|
+
restartTimer = null;
|
|
118
|
+
if (disposed || stopped || paused || !recognition) return;
|
|
119
|
+
try {
|
|
120
|
+
recognition.start();
|
|
121
|
+
} catch (error) {
|
|
122
|
+
failureReason =
|
|
123
|
+
error instanceof Error
|
|
124
|
+
? `Chrome Web Speech recognition could not restart: ${error.message}`
|
|
125
|
+
: "Chrome Web Speech recognition could not restart.";
|
|
126
|
+
}
|
|
127
|
+
}, RESTART_DELAY_MS);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const start = (): void => {
|
|
131
|
+
if (!Ctor || !enabled || disposed || stopped || recognition) return;
|
|
132
|
+
|
|
133
|
+
const nextRecognition = new Ctor();
|
|
134
|
+
recognition = nextRecognition;
|
|
135
|
+
nextRecognition.continuous = true;
|
|
136
|
+
nextRecognition.interimResults = true;
|
|
137
|
+
nextRecognition.lang = language;
|
|
138
|
+
nextRecognition.maxAlternatives = 1;
|
|
139
|
+
nextRecognition.onresult = (event) => {
|
|
140
|
+
let nextInterim = "";
|
|
141
|
+
for (
|
|
142
|
+
let index = event.resultIndex;
|
|
143
|
+
index < event.results.length;
|
|
144
|
+
index++
|
|
145
|
+
) {
|
|
146
|
+
const item = event.results[index];
|
|
147
|
+
const text = item?.[0]?.transcript ?? "";
|
|
148
|
+
if (item?.isFinal) finalText = appendTranscript(finalText, text);
|
|
149
|
+
else nextInterim = appendTranscript(nextInterim, text);
|
|
150
|
+
}
|
|
151
|
+
interimText = nextInterim;
|
|
152
|
+
};
|
|
153
|
+
nextRecognition.onerror = (event) => {
|
|
154
|
+
const error = event.error;
|
|
155
|
+
if (!error || error === "no-speech" || error === "aborted") return;
|
|
156
|
+
failureReason = `Chrome Web Speech recognition error: ${error}.`;
|
|
157
|
+
if (error === "not-allowed" || error === "service-not-allowed") {
|
|
158
|
+
stopped = true;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
nextRecognition.onend = () => {
|
|
162
|
+
if (disposed) return;
|
|
163
|
+
if (stopped) {
|
|
164
|
+
settleStop();
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (!paused) scheduleRestart();
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
try {
|
|
171
|
+
nextRecognition.start();
|
|
172
|
+
} catch (error) {
|
|
173
|
+
failureReason =
|
|
174
|
+
error instanceof Error
|
|
175
|
+
? `Chrome Web Speech recognition could not start: ${error.message}`
|
|
176
|
+
: "Chrome Web Speech recognition could not start.";
|
|
177
|
+
recognition = null;
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const stop = (): Promise<NativeTranscriptResult> => {
|
|
182
|
+
if (stopPromise) return stopPromise;
|
|
183
|
+
stopped = true;
|
|
184
|
+
paused = false;
|
|
185
|
+
if (restartTimer !== null) {
|
|
186
|
+
clearTimeout(restartTimer);
|
|
187
|
+
restartTimer = null;
|
|
188
|
+
}
|
|
189
|
+
if (!recognition) {
|
|
190
|
+
disposed = true;
|
|
191
|
+
return Promise.resolve(result());
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
stopPromise = new Promise<NativeTranscriptResult>((resolve) => {
|
|
195
|
+
resolveStop = resolve;
|
|
196
|
+
stopTimer = setTimeout(settleStop, STOP_SETTLE_MS);
|
|
197
|
+
try {
|
|
198
|
+
recognition?.stop();
|
|
199
|
+
} catch {
|
|
200
|
+
settleStop();
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
return stopPromise;
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const cancel = (): void => {
|
|
207
|
+
stopped = true;
|
|
208
|
+
disposed = true;
|
|
209
|
+
if (restartTimer !== null) clearTimeout(restartTimer);
|
|
210
|
+
if (stopTimer !== null) clearTimeout(stopTimer);
|
|
211
|
+
resolveStop = null;
|
|
212
|
+
try {
|
|
213
|
+
recognition?.abort();
|
|
214
|
+
} catch {
|
|
215
|
+
// Ignore teardown failures.
|
|
216
|
+
}
|
|
217
|
+
recognition = null;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
const pause = (): void => {
|
|
221
|
+
if (!recognition || stopped || disposed) return;
|
|
222
|
+
paused = true;
|
|
223
|
+
try {
|
|
224
|
+
recognition.stop();
|
|
225
|
+
} catch {
|
|
226
|
+
// The onend handler will settle the stopped recognition.
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const resume = (): void => {
|
|
231
|
+
if (!recognition || stopped || disposed) return;
|
|
232
|
+
paused = false;
|
|
233
|
+
try {
|
|
234
|
+
recognition.start();
|
|
235
|
+
} catch {
|
|
236
|
+
failureReason = "Chrome Web Speech recognition could not resume.";
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
supported: Boolean(Ctor && enabled),
|
|
242
|
+
start,
|
|
243
|
+
stop,
|
|
244
|
+
cancel,
|
|
245
|
+
pause,
|
|
246
|
+
resume,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
@@ -36,6 +36,10 @@ import {
|
|
|
36
36
|
import { MAX_UPLOAD_BYTES } from "@shared/upload-limits";
|
|
37
37
|
|
|
38
38
|
import { waitForReadyRecordingAfterFinalizeError } from "./finalize-recovery";
|
|
39
|
+
import {
|
|
40
|
+
createNativeTranscriptionCapture,
|
|
41
|
+
type NativeTranscriptionCapture,
|
|
42
|
+
} from "./native-transcription";
|
|
39
43
|
import {
|
|
40
44
|
createRecordingDurationState,
|
|
41
45
|
pauseRecordingDuration,
|
|
@@ -141,6 +145,7 @@ type BeginMessage = {
|
|
|
141
145
|
// Bearer token so chunk uploads authenticate the same way create-recording
|
|
142
146
|
// does. The offscreen document has no Clips session cookie of its own.
|
|
143
147
|
authToken?: string;
|
|
148
|
+
transcriptUrl?: string;
|
|
144
149
|
};
|
|
145
150
|
|
|
146
151
|
type SimpleMessage = {
|
|
@@ -172,6 +177,8 @@ type UploadResult = {
|
|
|
172
177
|
waitingForStorage?: boolean;
|
|
173
178
|
storageSetupRequired?: boolean;
|
|
174
179
|
error?: string;
|
|
180
|
+
nativeTranscript?: string;
|
|
181
|
+
nativeTranscriptFailure?: string;
|
|
175
182
|
};
|
|
176
183
|
|
|
177
184
|
type PreparedStreams = {
|
|
@@ -192,6 +199,7 @@ type ActiveRecording = {
|
|
|
192
199
|
uploadUrl: string;
|
|
193
200
|
uploadMode: UploadMode;
|
|
194
201
|
authToken: string | null;
|
|
202
|
+
transcriptUrl: string | null;
|
|
195
203
|
mode: CaptureMode;
|
|
196
204
|
startedAtMs: number;
|
|
197
205
|
duration: RecordingDurationState;
|
|
@@ -231,6 +239,10 @@ type ActiveRecording = {
|
|
|
231
239
|
dimensions: { width: number; height: number };
|
|
232
240
|
hasAudio: boolean;
|
|
233
241
|
hasCamera: boolean;
|
|
242
|
+
nativeTranscription: NativeTranscriptionCapture;
|
|
243
|
+
nativeTranscript: string;
|
|
244
|
+
nativeTranscriptFailure: string | null;
|
|
245
|
+
nativeTranscriptSaved: boolean;
|
|
234
246
|
stopped: Promise<UploadResult>;
|
|
235
247
|
resolveStopped: (result: UploadResult) => void;
|
|
236
248
|
rejectStopped: (error: Error) => void;
|
|
@@ -1224,6 +1236,7 @@ async function begin(message: BeginMessage): Promise<{
|
|
|
1224
1236
|
uploadUrl: message.uploadUrl,
|
|
1225
1237
|
uploadMode: message.uploadMode ?? "buffered",
|
|
1226
1238
|
authToken: message.authToken ?? null,
|
|
1239
|
+
transcriptUrl: message.transcriptUrl ?? null,
|
|
1227
1240
|
mode: ready.mode,
|
|
1228
1241
|
startedAtMs: 0,
|
|
1229
1242
|
duration: createRecordingDurationState(),
|
|
@@ -1259,6 +1272,12 @@ async function begin(message: BeginMessage): Promise<{
|
|
|
1259
1272
|
typeof message.hasCamera === "boolean"
|
|
1260
1273
|
? message.hasCamera
|
|
1261
1274
|
: ready.mode === "camera",
|
|
1275
|
+
nativeTranscription: createNativeTranscriptionCapture({
|
|
1276
|
+
enabled: Boolean(ready.micStream),
|
|
1277
|
+
}),
|
|
1278
|
+
nativeTranscript: "",
|
|
1279
|
+
nativeTranscriptFailure: null,
|
|
1280
|
+
nativeTranscriptSaved: false,
|
|
1262
1281
|
stopped,
|
|
1263
1282
|
resolveStopped,
|
|
1264
1283
|
rejectStopped,
|
|
@@ -1358,6 +1377,7 @@ function startRecorderNow(recording: ActiveRecording): void {
|
|
|
1358
1377
|
// Chime first (on "Go") so it mostly lands before the recording begins.
|
|
1359
1378
|
playStartChime();
|
|
1360
1379
|
recording.recorder.start(2000);
|
|
1380
|
+
recording.nativeTranscription.start();
|
|
1361
1381
|
recording.startedAtMs = Date.now();
|
|
1362
1382
|
recording.duration = startRecordingDuration(recording.startedAtMs);
|
|
1363
1383
|
console.log("[clips-offscreen] recorder.start ok");
|
|
@@ -1383,9 +1403,14 @@ function startRecorderNow(recording: ActiveRecording): void {
|
|
|
1383
1403
|
hasCamera: recording.hasCamera,
|
|
1384
1404
|
},
|
|
1385
1405
|
});
|
|
1406
|
+
recording.cancelled = true;
|
|
1407
|
+
recording.nativeTranscription.cancel();
|
|
1408
|
+
cleanup(recording);
|
|
1409
|
+
if (activeRecording === recording) activeRecording = null;
|
|
1386
1410
|
reportStatus(recording.sessionId, "error", {
|
|
1387
1411
|
recordingId: recording.recordingId,
|
|
1388
1412
|
error: err instanceof Error ? err.message : "Could not start recording.",
|
|
1413
|
+
recordingStep: "recorder-start",
|
|
1389
1414
|
});
|
|
1390
1415
|
}
|
|
1391
1416
|
}
|
|
@@ -1400,6 +1425,47 @@ function recordingDownloadFilename(recording: ActiveRecording): string {
|
|
|
1400
1425
|
return `clip-${stamp}.${ext}`;
|
|
1401
1426
|
}
|
|
1402
1427
|
|
|
1428
|
+
async function saveNativeTranscript(recording: ActiveRecording): Promise<void> {
|
|
1429
|
+
if (recording.nativeTranscriptSaved || !recording.transcriptUrl) return;
|
|
1430
|
+
const captured = await recording.nativeTranscription.stop();
|
|
1431
|
+
recording.nativeTranscript = captured.text.trim();
|
|
1432
|
+
recording.nativeTranscriptFailure = captured.failureReason;
|
|
1433
|
+
|
|
1434
|
+
const body = recording.nativeTranscript
|
|
1435
|
+
? {
|
|
1436
|
+
recordingId: recording.recordingId,
|
|
1437
|
+
fullText: recording.nativeTranscript,
|
|
1438
|
+
source: "web-speech",
|
|
1439
|
+
}
|
|
1440
|
+
: {
|
|
1441
|
+
recordingId: recording.recordingId,
|
|
1442
|
+
fullText: "",
|
|
1443
|
+
source: "web-speech",
|
|
1444
|
+
failureReason:
|
|
1445
|
+
recording.nativeTranscriptFailure ||
|
|
1446
|
+
"Chrome Web Speech recognition returned no transcript.",
|
|
1447
|
+
};
|
|
1448
|
+
const headers: Record<string, string> = {
|
|
1449
|
+
"Content-Type": "application/json",
|
|
1450
|
+
"X-Agent-Native-Frontend": "1",
|
|
1451
|
+
...(recording.authToken
|
|
1452
|
+
? { Authorization: `Bearer ${recording.authToken}` }
|
|
1453
|
+
: {}),
|
|
1454
|
+
};
|
|
1455
|
+
const response = await fetch(recording.transcriptUrl, {
|
|
1456
|
+
method: "POST",
|
|
1457
|
+
headers,
|
|
1458
|
+
credentials: "include",
|
|
1459
|
+
cache: "no-store",
|
|
1460
|
+
body: JSON.stringify(body),
|
|
1461
|
+
signal: AbortSignal.timeout(5_000),
|
|
1462
|
+
});
|
|
1463
|
+
if (!response.ok) {
|
|
1464
|
+
throw new Error(`Native transcript save failed (${response.status}).`);
|
|
1465
|
+
}
|
|
1466
|
+
recording.nativeTranscriptSaved = true;
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1403
1469
|
// Last-resort recovery: if a finished recording can't be uploaded, save the
|
|
1404
1470
|
// locally-buffered bytes to the user's Downloads so the recording is never
|
|
1405
1471
|
// lost. The offscreen document can't call chrome.downloads, so it hands the
|
|
@@ -1461,6 +1527,18 @@ async function finalizeStop(recording: ActiveRecording): Promise<void> {
|
|
|
1461
1527
|
// spent paused is excluded by pauseRecordingDuration().
|
|
1462
1528
|
recording.duration = pauseRecordingDuration(recording.duration, Date.now());
|
|
1463
1529
|
const durationMs = recording.duration.elapsedMs;
|
|
1530
|
+
try {
|
|
1531
|
+
await saveNativeTranscript(recording);
|
|
1532
|
+
} catch (error) {
|
|
1533
|
+
console.warn("[clips-offscreen] native transcript save failed", error);
|
|
1534
|
+
captureExtensionError(error, {
|
|
1535
|
+
tags: {
|
|
1536
|
+
surface: "offscreen",
|
|
1537
|
+
recordingStep: "save-native-transcript",
|
|
1538
|
+
},
|
|
1539
|
+
extra: { recordingId: recording.recordingId },
|
|
1540
|
+
});
|
|
1541
|
+
}
|
|
1464
1542
|
reportStatus(recording.sessionId, "uploading", {
|
|
1465
1543
|
recordingId: recording.recordingId,
|
|
1466
1544
|
});
|
|
@@ -1514,6 +1592,15 @@ async function finalizeStop(recording: ActiveRecording): Promise<void> {
|
|
|
1514
1592
|
hasAudio: recording.hasAudio,
|
|
1515
1593
|
hasCamera: recording.hasCamera,
|
|
1516
1594
|
});
|
|
1595
|
+
result = {
|
|
1596
|
+
...result,
|
|
1597
|
+
...(recording.nativeTranscript
|
|
1598
|
+
? { nativeTranscript: recording.nativeTranscript }
|
|
1599
|
+
: {}),
|
|
1600
|
+
...(recording.nativeTranscriptFailure
|
|
1601
|
+
? { nativeTranscriptFailure: recording.nativeTranscriptFailure }
|
|
1602
|
+
: {}),
|
|
1603
|
+
};
|
|
1517
1604
|
} catch (err) {
|
|
1518
1605
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
1519
1606
|
(error as { finalUpload?: boolean }).finalUpload = true;
|
|
@@ -1590,6 +1677,7 @@ function pause(message: SimpleMessage): { ok: boolean } {
|
|
|
1590
1677
|
if (recording && recording.sessionId === message.sessionId) {
|
|
1591
1678
|
if (recording.recorder.state === "recording") {
|
|
1592
1679
|
recording.recorder.pause();
|
|
1680
|
+
recording.nativeTranscription.pause();
|
|
1593
1681
|
recording.duration = pauseRecordingDuration(
|
|
1594
1682
|
recording.duration,
|
|
1595
1683
|
Date.now(),
|
|
@@ -1607,6 +1695,7 @@ function resume(message: SimpleMessage): { ok: boolean } {
|
|
|
1607
1695
|
if (recording && recording.sessionId === message.sessionId) {
|
|
1608
1696
|
if (recording.recorder.state === "paused") {
|
|
1609
1697
|
recording.recorder.resume();
|
|
1698
|
+
recording.nativeTranscription.resume();
|
|
1610
1699
|
recording.duration = resumeRecordingDuration(
|
|
1611
1700
|
recording.duration,
|
|
1612
1701
|
Date.now(),
|
|
@@ -1644,6 +1733,7 @@ function cancel(message: SimpleMessage): { ok: boolean } {
|
|
|
1644
1733
|
const recording = activeRecording;
|
|
1645
1734
|
if (recording && recording.sessionId === message.sessionId) {
|
|
1646
1735
|
recording.cancelled = true;
|
|
1736
|
+
recording.nativeTranscription.cancel();
|
|
1647
1737
|
if (recording.startTimer !== null) {
|
|
1648
1738
|
clearTimeout(recording.startTimer);
|
|
1649
1739
|
recording.startTimer = null;
|
|
@@ -1673,6 +1763,18 @@ function startNow(message: SimpleMessage): { ok: boolean } {
|
|
|
1673
1763
|
return { ok: true };
|
|
1674
1764
|
}
|
|
1675
1765
|
|
|
1766
|
+
function getRecordingState(): {
|
|
1767
|
+
ok: boolean;
|
|
1768
|
+
activeSessionId?: string;
|
|
1769
|
+
preparedSessionId?: string;
|
|
1770
|
+
} {
|
|
1771
|
+
return {
|
|
1772
|
+
ok: true,
|
|
1773
|
+
...(activeRecording ? { activeSessionId: activeRecording.sessionId } : {}),
|
|
1774
|
+
...(prepared ? { preparedSessionId: prepared.sessionId } : {}),
|
|
1775
|
+
};
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1676
1778
|
// Restart: discard the in-progress recording but keep the same source streams
|
|
1677
1779
|
// (so the user does not have to re-pick a screen), then re-home them into a
|
|
1678
1780
|
// prepared slot. A fresh recorder is built on the next BEGIN.
|
|
@@ -1687,6 +1789,7 @@ async function restart(
|
|
|
1687
1789
|
// handler ignores the final flush, so the source tracks stay live.
|
|
1688
1790
|
recording.restarting = true;
|
|
1689
1791
|
recording.cancelled = true;
|
|
1792
|
+
recording.nativeTranscription.cancel();
|
|
1690
1793
|
if (recording.recorder.state !== "inactive") recording.recorder.stop();
|
|
1691
1794
|
// Tear down the old compositor + mixing context; keep the capture tracks alive
|
|
1692
1795
|
// so the next BEGIN can build a fresh compositor/recorder on the same streams.
|
|
@@ -1741,6 +1844,9 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
|
|
1741
1844
|
case "CLIPS_OFFSCREEN_START_NOW":
|
|
1742
1845
|
task = Promise.resolve(startNow(message as SimpleMessage));
|
|
1743
1846
|
break;
|
|
1847
|
+
case "CLIPS_OFFSCREEN_STATUS":
|
|
1848
|
+
task = Promise.resolve(getRecordingState());
|
|
1849
|
+
break;
|
|
1744
1850
|
case "CLIPS_OFFSCREEN_COPY_TEXT":
|
|
1745
1851
|
task = copyTextToClipboard(message as CopyTextMessage);
|
|
1746
1852
|
break;
|