@agent-native/core 0.98.17 → 0.99.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +25 -0
- package/corpus/core/docs/content/actions.mdx +1 -1
- package/corpus/core/docs/content/authentication.mdx +1 -1
- package/corpus/core/docs/content/dispatch.mdx +3 -3
- package/corpus/core/docs/content/external-agents.mdx +30 -19
- package/corpus/core/docs/content/locales/ar-SA/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/ar-SA/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/ar-SA/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/ar-SA/external-agents.mdx +23 -19
- package/corpus/core/docs/content/locales/ar-SA/mcp-clients.mdx +31 -3
- package/corpus/core/docs/content/locales/ar-SA/mcp-protocol.mdx +29 -15
- package/corpus/core/docs/content/locales/ar-SA/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/ar-SA/server.mdx +2 -2
- package/corpus/core/docs/content/locales/ar-SA/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/ar-SA/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/ar-SA/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/ar-SA/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/de-DE/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/de-DE/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/de-DE/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/de-DE/external-agents.mdx +23 -19
- package/corpus/core/docs/content/locales/de-DE/mcp-clients.mdx +37 -3
- package/corpus/core/docs/content/locales/de-DE/mcp-protocol.mdx +29 -15
- package/corpus/core/docs/content/locales/de-DE/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/de-DE/server.mdx +2 -2
- package/corpus/core/docs/content/locales/de-DE/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/de-DE/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/de-DE/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/de-DE/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/es-ES/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/es-ES/external-agents.mdx +32 -19
- package/corpus/core/docs/content/locales/es-ES/mcp-clients.mdx +17 -3
- package/corpus/core/docs/content/locales/es-ES/mcp-protocol.mdx +38 -15
- package/corpus/core/docs/content/locales/es-ES/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/es-ES/server.mdx +2 -2
- package/corpus/core/docs/content/locales/es-ES/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/es-ES/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/fr-FR/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/fr-FR/external-agents.mdx +23 -19
- package/corpus/core/docs/content/locales/fr-FR/mcp-clients.mdx +17 -3
- package/corpus/core/docs/content/locales/fr-FR/mcp-protocol.mdx +29 -15
- package/corpus/core/docs/content/locales/fr-FR/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/fr-FR/server.mdx +2 -2
- package/corpus/core/docs/content/locales/fr-FR/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/fr-FR/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/hi-IN/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/hi-IN/external-agents.mdx +31 -19
- package/corpus/core/docs/content/locales/hi-IN/mcp-clients.mdx +17 -3
- package/corpus/core/docs/content/locales/hi-IN/mcp-protocol.mdx +36 -15
- package/corpus/core/docs/content/locales/hi-IN/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/hi-IN/server.mdx +2 -2
- package/corpus/core/docs/content/locales/hi-IN/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/hi-IN/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/ja-JP/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/ja-JP/external-agents.mdx +23 -19
- package/corpus/core/docs/content/locales/ja-JP/mcp-clients.mdx +34 -3
- package/corpus/core/docs/content/locales/ja-JP/mcp-protocol.mdx +29 -15
- package/corpus/core/docs/content/locales/ja-JP/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/ja-JP/server.mdx +2 -2
- package/corpus/core/docs/content/locales/ja-JP/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/ja-JP/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/ko-KR/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/ko-KR/external-agents.mdx +30 -19
- package/corpus/core/docs/content/locales/ko-KR/mcp-clients.mdx +33 -3
- package/corpus/core/docs/content/locales/ko-KR/mcp-protocol.mdx +36 -15
- package/corpus/core/docs/content/locales/ko-KR/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/ko-KR/server.mdx +2 -2
- package/corpus/core/docs/content/locales/ko-KR/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/ko-KR/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/pt-BR/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/pt-BR/external-agents.mdx +32 -19
- package/corpus/core/docs/content/locales/pt-BR/mcp-clients.mdx +34 -3
- package/corpus/core/docs/content/locales/pt-BR/mcp-protocol.mdx +32 -15
- package/corpus/core/docs/content/locales/pt-BR/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/pt-BR/server.mdx +2 -2
- package/corpus/core/docs/content/locales/pt-BR/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/pt-BR/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-CN/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-CN/external-agents.mdx +23 -19
- package/corpus/core/docs/content/locales/zh-CN/mcp-clients.mdx +28 -3
- package/corpus/core/docs/content/locales/zh-CN/mcp-protocol.mdx +29 -15
- package/corpus/core/docs/content/locales/zh-CN/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-CN/server.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-CN/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-CN/template-plan.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-TW/actions.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/authentication.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/dispatch.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-TW/external-agents.mdx +23 -19
- package/corpus/core/docs/content/locales/zh-TW/mcp-clients.mdx +28 -3
- package/corpus/core/docs/content/locales/zh-TW/mcp-protocol.mdx +30 -15
- package/corpus/core/docs/content/locales/zh-TW/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-TW/server.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-TW/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/template-assets.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-TW/template-plan.mdx +3 -3
- package/corpus/core/docs/content/mcp-clients.mdx +31 -4
- package/corpus/core/docs/content/mcp-protocol.mdx +35 -15
- package/corpus/core/docs/content/plan-plugin.mdx +3 -3
- package/corpus/core/docs/content/server.mdx +2 -2
- package/corpus/core/docs/content/skills-guide.mdx +1 -1
- package/corpus/core/docs/content/template-assets.mdx +1 -1
- package/corpus/core/docs/content/template-dispatch.mdx +2 -2
- package/corpus/core/docs/content/template-plan.mdx +3 -3
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/client.ts +3 -0
- package/corpus/core/src/a2a/handlers.ts +95 -7
- package/corpus/core/src/agent/production-agent.ts +21 -0
- package/corpus/core/src/cli/connect.ts +50 -24
- package/corpus/core/src/cli/mcp-config-writers.ts +10 -0
- package/corpus/core/src/cli/mcp.ts +5 -5
- package/corpus/core/src/cli/pr-visual-recap-workflow.ts +1 -1
- package/corpus/core/src/cli/skills-content/assets-skill.ts +1 -1
- package/corpus/core/src/cli/skills-content/design-exploration-skill.ts +1 -1
- package/corpus/core/src/cli/skills-content/help.ts +1 -1
- package/corpus/core/src/cli/skills-content/plan-setup-auth.ts +1 -1
- package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +1 -1
- package/corpus/core/src/cli/skills-content/visual-recap-skill.ts +2 -2
- package/corpus/core/src/cli/skills.ts +23 -12
- package/corpus/core/src/client/analytics.ts +13 -0
- package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +5 -0
- package/corpus/core/src/client/resources/mcp-integration-catalog.ts +17 -0
- package/corpus/core/src/embedding/agent.ts +8 -6
- package/corpus/core/src/localization/default-messages.ts +7 -0
- package/corpus/core/src/mcp/ask-app-inline-tasks.ts +125 -0
- package/corpus/core/src/mcp/build-server.ts +65 -3
- package/corpus/core/src/mcp/builtin-tools.ts +186 -22
- package/corpus/core/src/mcp/connect-route.ts +17 -14
- package/corpus/core/src/mcp/oauth-route.ts +38 -13
- package/corpus/core/src/mcp/route-paths.ts +34 -0
- package/corpus/core/src/mcp/server.ts +21 -10
- package/corpus/core/src/mcp/stdio.ts +34 -16
- package/corpus/core/src/mcp/workspace-resolve.ts +2 -1
- package/corpus/core/src/mcp-client/manager.ts +5 -3
- package/corpus/core/src/mcp-client/remote-store.ts +10 -10
- package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +13 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +42 -9
- package/corpus/core/src/server/agent-teams.ts +17 -0
- package/corpus/core/src/server/auth.ts +22 -6
- package/corpus/core/src/server/core-routes-plugin.ts +30 -24
- package/corpus/core/src/server/csrf.ts +17 -0
- package/corpus/core/src/server/framework-request-handler.ts +8 -2
- package/corpus/core/src/server/google-oauth.ts +12 -2
- package/corpus/core/src/server/http-response-telemetry.ts +6 -1
- package/corpus/core/src/server/recap-image-route.ts +3 -3
- package/corpus/core/src/server/security-headers.ts +7 -1
- package/corpus/core/src/server/ssr-handler.ts +2 -0
- package/corpus/core/src/shared/cache-control.ts +6 -4
- package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +10 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +15 -6
- package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +16 -10
- package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +20 -1
- package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/analytics/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/analytics/app/assets/replay-cursor.svg +17 -0
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +4 -3
- package/corpus/templates/analytics/app/global.css +71 -4
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +32 -4
- package/corpus/templates/analytics/app/pages/monitoring/errors/IssueDetail.tsx +1 -1
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +49 -11
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +4 -6
- package/corpus/templates/analytics/changelog/2026-07-13-all-time-dashboard-filters-no-longer-send-invalid-dates-to-b.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-13-daily-dashboard-emails-recover-more-reliably-from-serverless.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-13-error-issue-titles-wrap-instead-of-overflowing.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-13-saving-a-new-dashboard-view-no-longer-fails-with-a-server-er.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-13-session-replay-cursors-stay-hidden-until-their-first-recorde.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-13-session-replay-links-now-support-cmd-click-and-middle-click-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-13-session-replays-keep-a-visible-mac-style-cursor-over-the-vis.md +6 -0
- package/corpus/templates/analytics/server/jobs/dashboard-report.ts +21 -2
- package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +57 -1
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +266 -28
- package/corpus/templates/analytics/server/lib/dashboards-store.ts +43 -4
- package/corpus/templates/analytics/server/lib/error-capture.ts +24 -5
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +5 -0
- package/corpus/templates/analytics/server/routes/[...page].get.ts +0 -2
- package/corpus/templates/assets/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/assets/agent-native.app-skill.json +1 -1
- package/corpus/templates/brain/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/calendar/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/calendar/AGENTS.md +2 -1
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +0 -19
- package/corpus/templates/calendar/app/lib/attendee-local-time.ts +14 -5
- package/corpus/templates/calendar/changelog/2026-07-13-your-local-time-now-follows-your-browser-timezone-and-event-.md +6 -0
- package/corpus/templates/chat/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/clips/.agents/skills/recording/SKILL.md +7 -2
- package/corpus/templates/clips/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/clips/AGENTS.md +7 -0
- package/corpus/templates/clips/actions/list-meetings.ts +19 -4
- package/corpus/templates/clips/actions/start-meeting-recording.ts +7 -1
- package/corpus/templates/clips/app/components/library/recording-card.tsx +27 -26
- package/corpus/templates/clips/app/components/library/space-card.tsx +4 -6
- package/corpus/templates/clips/app/components/meetings/transcript-bubbles.tsx +75 -78
- package/corpus/templates/clips/app/components/recorder/confetti-canvas.tsx +18 -1
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +6 -12
- package/corpus/templates/clips/app/components/recorder/recording-toolbar.tsx +19 -2
- package/corpus/templates/clips/app/lib/camera-composite.ts +70 -10
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +1 -1
- package/corpus/templates/clips/app/routes/record.tsx +5 -25
- package/corpus/templates/clips/changelog/2026-07-13-clips-desktop-now-requires-macos-13-for-native-capture.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-13-clips-hide-solo-meeting-reminders.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-13-clips-now-removes-duplicate-mic-and-system-transcript-turns-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-13-desktop-recordings-run-cooler-and-quieter-live-transcription.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-13-meeting-recordings-now-stop-after-a-calendar-meeting-ends-an.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-13-meeting-transcripts-now-use-a-clean-agent-chat-style-reading.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-13-screen-recordings-use-less-processing-power-during-longer-ca.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/background.ts +5 -3
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +17 -14
- package/corpus/templates/clips/chrome-extension/src/overlay.ts +8 -2
- package/corpus/templates/clips/desktop/README.md +3 -0
- package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +9 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +8 -2
- package/corpus/templates/clips/desktop/src/lib/silence-events.ts +1 -0
- package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +5 -0
- package/corpus/templates/clips/desktop/src/lib/transcription-engine.ts +134 -5
- package/corpus/templates/clips/desktop/src/lib/upload-video-stream.ts +28 -0
- package/corpus/templates/clips/desktop/src/overlays/flow-bar.tsx +10 -3
- package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +42 -9
- package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +10 -2
- package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +6 -1
- package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +77 -1
- package/corpus/templates/clips/desktop/src-tauri/src/silence_detector.rs +104 -25
- package/corpus/templates/clips/desktop/src-tauri/src/system_audio.rs +4 -0
- package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +287 -32
- package/corpus/templates/clips/desktop/src-tauri/tauri.conf.json +1 -1
- package/corpus/templates/clips/server/lib/calendar-event-classification.ts +28 -0
- package/corpus/templates/clips/server/routes/[...page].get.ts +1 -59
- package/corpus/templates/clips/shared/recording-capture.ts +37 -0
- package/corpus/templates/content/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/content/agent-native.app-skill.json +1 -1
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +18 -16
- package/corpus/templates/content/server/routes/[...page].get.ts +1 -15
- package/corpus/templates/design/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/design/actions/connect-assets-mcp.ts +1 -1
- package/corpus/templates/design/agent-native.app-skill.json +1 -1
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +88 -12
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +1 -0
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +4 -1
- package/corpus/templates/design/changelog/2026-07-13-adding-shapes-preserves-canvas-background.md +6 -0
- package/corpus/templates/design/changelog/2026-07-13-clicking-quickly-between-overlapping-elements-no-longer-bounc.md +6 -0
- package/corpus/templates/design/server/plugins/assets-mcp.ts +1 -1
- package/corpus/templates/design/server/routes/[...page].get.ts +0 -2
- package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/forms/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/macros/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/mail/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/plan/.agents/skills/security/SKILL.md +10 -0
- package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +1 -1
- package/corpus/templates/plan/.agents/skills/visual-recap/SKILL.md +2 -2
- package/corpus/templates/plan/agent-native.app-skill.json +1 -1
- package/corpus/templates/plan/app/lib/plan-local-bridge.ts +6 -1
- package/corpus/templates/plan/app/pages/PlansPage.tsx +15 -6
- package/corpus/templates/plan/changelog/2026-07-13-fixed-local-plan-previews-continuously-flickering-while-revi.md +6 -0
- package/corpus/templates/plan/server/routes/[...page].get.ts +0 -2
- package/corpus/templates/slides/.agents/skills/security/SKILL.md +10 -0
- package/dist/a2a/client.d.ts +2 -0
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +2 -0
- package/dist/a2a/client.js.map +1 -1
- package/dist/a2a/handlers.d.ts.map +1 -1
- package/dist/a2a/handlers.js +84 -7
- package/dist/a2a/handlers.js.map +1 -1
- package/dist/agent/production-agent.d.ts +9 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +12 -0
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/connect.d.ts +2 -2
- package/dist/cli/connect.d.ts.map +1 -1
- package/dist/cli/connect.js +45 -23
- package/dist/cli/connect.js.map +1 -1
- package/dist/cli/mcp-config-writers.d.ts.map +1 -1
- package/dist/cli/mcp-config-writers.js +7 -0
- package/dist/cli/mcp-config-writers.js.map +1 -1
- package/dist/cli/mcp.js +5 -3
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.js +1 -1
- package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
- package/dist/cli/skills-content/assets-skill.d.ts +1 -1
- package/dist/cli/skills-content/assets-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/assets-skill.js +1 -1
- package/dist/cli/skills-content/assets-skill.js.map +1 -1
- package/dist/cli/skills-content/design-exploration-skill.d.ts +1 -1
- package/dist/cli/skills-content/design-exploration-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/design-exploration-skill.js +1 -1
- package/dist/cli/skills-content/design-exploration-skill.js.map +1 -1
- package/dist/cli/skills-content/help.d.ts +1 -1
- package/dist/cli/skills-content/help.d.ts.map +1 -1
- package/dist/cli/skills-content/help.js +1 -1
- package/dist/cli/skills-content/help.js.map +1 -1
- package/dist/cli/skills-content/plan-setup-auth.d.ts +1 -1
- package/dist/cli/skills-content/plan-setup-auth.d.ts.map +1 -1
- package/dist/cli/skills-content/plan-setup-auth.js +1 -1
- package/dist/cli/skills-content/plan-setup-auth.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 +1 -1
- package/dist/cli/skills-content/visual-plan-skill.js.map +1 -1
- package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
- package/dist/cli/skills-content/visual-recap-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/visual-recap-skill.js +2 -2
- package/dist/cli/skills-content/visual-recap-skill.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +16 -12
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +11 -0
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
- package/dist/client/resources/McpIntegrationDialog.js +1 -1
- package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.d.ts +1 -0
- package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.js +14 -0
- package/dist/client/resources/mcp-integration-catalog.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/collab/struct-routes.d.ts +1 -1
- package/dist/embedding/agent.d.ts.map +1 -1
- package/dist/embedding/agent.js +6 -7
- package/dist/embedding/agent.js.map +1 -1
- package/dist/localization/default-messages.d.ts +5 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +5 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/mcp/ask-app-inline-tasks.d.ts +47 -0
- package/dist/mcp/ask-app-inline-tasks.d.ts.map +1 -0
- package/dist/mcp/ask-app-inline-tasks.js +87 -0
- package/dist/mcp/ask-app-inline-tasks.js.map +1 -0
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +56 -3
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/builtin-tools.d.ts.map +1 -1
- package/dist/mcp/builtin-tools.js +141 -21
- package/dist/mcp/builtin-tools.js.map +1 -1
- package/dist/mcp/connect-route.d.ts +12 -10
- package/dist/mcp/connect-route.d.ts.map +1 -1
- package/dist/mcp/connect-route.js +17 -14
- package/dist/mcp/connect-route.js.map +1 -1
- package/dist/mcp/oauth-route.d.ts +1 -1
- package/dist/mcp/oauth-route.d.ts.map +1 -1
- package/dist/mcp/oauth-route.js +30 -13
- package/dist/mcp/oauth-route.js.map +1 -1
- package/dist/mcp/route-paths.d.ts +13 -0
- package/dist/mcp/route-paths.d.ts.map +1 -0
- package/dist/mcp/route-paths.js +27 -0
- package/dist/mcp/route-paths.js.map +1 -0
- package/dist/mcp/server.d.ts +2 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +14 -6
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/stdio.d.ts +7 -6
- package/dist/mcp/stdio.d.ts.map +1 -1
- package/dist/mcp/stdio.js +27 -15
- package/dist/mcp/stdio.js.map +1 -1
- package/dist/mcp/workspace-resolve.d.ts +2 -1
- package/dist/mcp/workspace-resolve.d.ts.map +1 -1
- package/dist/mcp/workspace-resolve.js +2 -1
- package/dist/mcp/workspace-resolve.js.map +1 -1
- package/dist/mcp-client/manager.js +6 -3
- package/dist/mcp-client/manager.js.map +1 -1
- package/dist/mcp-client/remote-store.js +5 -7
- package/dist/mcp-client/remote-store.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
- package/dist/server/agent-chat/action-filters-a2a.js +11 -1
- package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +43 -11
- 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/agent-teams.d.ts.map +1 -1
- package/dist/server/agent-teams.js +15 -1
- package/dist/server/agent-teams.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +16 -6
- package/dist/server/auth.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +4 -3
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +20 -15
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/csrf.d.ts.map +1 -1
- package/dist/server/csrf.js +11 -0
- package/dist/server/csrf.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +8 -2
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/server/google-oauth.d.ts +2 -0
- package/dist/server/google-oauth.d.ts.map +1 -1
- package/dist/server/google-oauth.js +11 -2
- package/dist/server/google-oauth.js.map +1 -1
- package/dist/server/http-response-telemetry.d.ts.map +1 -1
- package/dist/server/http-response-telemetry.js +4 -1
- package/dist/server/http-response-telemetry.js.map +1 -1
- package/dist/server/recap-image-route.js +3 -3
- package/dist/server/recap-image-route.js.map +1 -1
- package/dist/server/security-headers.d.ts.map +1 -1
- package/dist/server/security-headers.js +4 -1
- package/dist/server/security-headers.js.map +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +3 -1
- package/dist/server/ssr-handler.js.map +1 -1
- package/dist/shared/cache-control.d.ts +7 -6
- package/dist/shared/cache-control.d.ts.map +1 -1
- package/dist/shared/cache-control.js +4 -3
- package/dist/shared/cache-control.js.map +1 -1
- package/dist/templates/default/.agents/skills/security/SKILL.md +10 -0
- package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +15 -6
- package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +16 -10
- package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +20 -1
- package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +10 -0
- package/docs/content/actions.mdx +1 -1
- package/docs/content/authentication.mdx +1 -1
- package/docs/content/dispatch.mdx +3 -3
- package/docs/content/external-agents.mdx +30 -19
- package/docs/content/locales/ar-SA/actions.mdx +1 -1
- package/docs/content/locales/ar-SA/authentication.mdx +1 -1
- package/docs/content/locales/ar-SA/dispatch.mdx +3 -3
- package/docs/content/locales/ar-SA/external-agents.mdx +23 -19
- package/docs/content/locales/ar-SA/mcp-clients.mdx +31 -3
- package/docs/content/locales/ar-SA/mcp-protocol.mdx +29 -15
- package/docs/content/locales/ar-SA/plan-plugin.mdx +3 -3
- package/docs/content/locales/ar-SA/server.mdx +2 -2
- package/docs/content/locales/ar-SA/skills-guide.mdx +1 -1
- package/docs/content/locales/ar-SA/template-assets.mdx +1 -1
- package/docs/content/locales/ar-SA/template-dispatch.mdx +2 -2
- package/docs/content/locales/ar-SA/template-plan.mdx +3 -3
- package/docs/content/locales/de-DE/actions.mdx +1 -1
- package/docs/content/locales/de-DE/authentication.mdx +1 -1
- package/docs/content/locales/de-DE/dispatch.mdx +3 -3
- package/docs/content/locales/de-DE/external-agents.mdx +23 -19
- package/docs/content/locales/de-DE/mcp-clients.mdx +37 -3
- package/docs/content/locales/de-DE/mcp-protocol.mdx +29 -15
- package/docs/content/locales/de-DE/plan-plugin.mdx +3 -3
- package/docs/content/locales/de-DE/server.mdx +2 -2
- package/docs/content/locales/de-DE/skills-guide.mdx +1 -1
- package/docs/content/locales/de-DE/template-assets.mdx +1 -1
- package/docs/content/locales/de-DE/template-dispatch.mdx +2 -2
- package/docs/content/locales/de-DE/template-plan.mdx +3 -3
- package/docs/content/locales/es-ES/actions.mdx +1 -1
- package/docs/content/locales/es-ES/authentication.mdx +1 -1
- package/docs/content/locales/es-ES/dispatch.mdx +3 -3
- package/docs/content/locales/es-ES/external-agents.mdx +32 -19
- package/docs/content/locales/es-ES/mcp-clients.mdx +17 -3
- package/docs/content/locales/es-ES/mcp-protocol.mdx +38 -15
- package/docs/content/locales/es-ES/plan-plugin.mdx +3 -3
- package/docs/content/locales/es-ES/server.mdx +2 -2
- package/docs/content/locales/es-ES/skills-guide.mdx +1 -1
- package/docs/content/locales/es-ES/template-assets.mdx +1 -1
- package/docs/content/locales/es-ES/template-dispatch.mdx +2 -2
- package/docs/content/locales/es-ES/template-plan.mdx +3 -3
- package/docs/content/locales/fr-FR/actions.mdx +1 -1
- package/docs/content/locales/fr-FR/authentication.mdx +1 -1
- package/docs/content/locales/fr-FR/dispatch.mdx +3 -3
- package/docs/content/locales/fr-FR/external-agents.mdx +23 -19
- package/docs/content/locales/fr-FR/mcp-clients.mdx +17 -3
- package/docs/content/locales/fr-FR/mcp-protocol.mdx +29 -15
- package/docs/content/locales/fr-FR/plan-plugin.mdx +3 -3
- package/docs/content/locales/fr-FR/server.mdx +2 -2
- package/docs/content/locales/fr-FR/skills-guide.mdx +1 -1
- package/docs/content/locales/fr-FR/template-assets.mdx +1 -1
- package/docs/content/locales/fr-FR/template-dispatch.mdx +2 -2
- package/docs/content/locales/fr-FR/template-plan.mdx +3 -3
- package/docs/content/locales/hi-IN/actions.mdx +1 -1
- package/docs/content/locales/hi-IN/authentication.mdx +1 -1
- package/docs/content/locales/hi-IN/dispatch.mdx +3 -3
- package/docs/content/locales/hi-IN/external-agents.mdx +31 -19
- package/docs/content/locales/hi-IN/mcp-clients.mdx +17 -3
- package/docs/content/locales/hi-IN/mcp-protocol.mdx +36 -15
- package/docs/content/locales/hi-IN/plan-plugin.mdx +3 -3
- package/docs/content/locales/hi-IN/server.mdx +2 -2
- package/docs/content/locales/hi-IN/skills-guide.mdx +1 -1
- package/docs/content/locales/hi-IN/template-assets.mdx +1 -1
- package/docs/content/locales/hi-IN/template-dispatch.mdx +2 -2
- package/docs/content/locales/hi-IN/template-plan.mdx +3 -3
- package/docs/content/locales/ja-JP/actions.mdx +1 -1
- package/docs/content/locales/ja-JP/authentication.mdx +1 -1
- package/docs/content/locales/ja-JP/dispatch.mdx +3 -3
- package/docs/content/locales/ja-JP/external-agents.mdx +23 -19
- package/docs/content/locales/ja-JP/mcp-clients.mdx +34 -3
- package/docs/content/locales/ja-JP/mcp-protocol.mdx +29 -15
- package/docs/content/locales/ja-JP/plan-plugin.mdx +3 -3
- package/docs/content/locales/ja-JP/server.mdx +2 -2
- package/docs/content/locales/ja-JP/skills-guide.mdx +1 -1
- package/docs/content/locales/ja-JP/template-assets.mdx +1 -1
- package/docs/content/locales/ja-JP/template-dispatch.mdx +2 -2
- package/docs/content/locales/ja-JP/template-plan.mdx +3 -3
- package/docs/content/locales/ko-KR/actions.mdx +1 -1
- package/docs/content/locales/ko-KR/authentication.mdx +1 -1
- package/docs/content/locales/ko-KR/dispatch.mdx +3 -3
- package/docs/content/locales/ko-KR/external-agents.mdx +30 -19
- package/docs/content/locales/ko-KR/mcp-clients.mdx +33 -3
- package/docs/content/locales/ko-KR/mcp-protocol.mdx +36 -15
- package/docs/content/locales/ko-KR/plan-plugin.mdx +3 -3
- package/docs/content/locales/ko-KR/server.mdx +2 -2
- package/docs/content/locales/ko-KR/skills-guide.mdx +1 -1
- package/docs/content/locales/ko-KR/template-assets.mdx +1 -1
- package/docs/content/locales/ko-KR/template-dispatch.mdx +2 -2
- package/docs/content/locales/ko-KR/template-plan.mdx +3 -3
- package/docs/content/locales/pt-BR/actions.mdx +1 -1
- package/docs/content/locales/pt-BR/authentication.mdx +1 -1
- package/docs/content/locales/pt-BR/dispatch.mdx +3 -3
- package/docs/content/locales/pt-BR/external-agents.mdx +32 -19
- package/docs/content/locales/pt-BR/mcp-clients.mdx +34 -3
- package/docs/content/locales/pt-BR/mcp-protocol.mdx +32 -15
- package/docs/content/locales/pt-BR/plan-plugin.mdx +3 -3
- package/docs/content/locales/pt-BR/server.mdx +2 -2
- package/docs/content/locales/pt-BR/skills-guide.mdx +1 -1
- package/docs/content/locales/pt-BR/template-assets.mdx +1 -1
- package/docs/content/locales/pt-BR/template-dispatch.mdx +2 -2
- package/docs/content/locales/pt-BR/template-plan.mdx +3 -3
- package/docs/content/locales/zh-CN/actions.mdx +1 -1
- package/docs/content/locales/zh-CN/authentication.mdx +1 -1
- package/docs/content/locales/zh-CN/dispatch.mdx +3 -3
- package/docs/content/locales/zh-CN/external-agents.mdx +23 -19
- package/docs/content/locales/zh-CN/mcp-clients.mdx +28 -3
- package/docs/content/locales/zh-CN/mcp-protocol.mdx +29 -15
- package/docs/content/locales/zh-CN/plan-plugin.mdx +3 -3
- package/docs/content/locales/zh-CN/server.mdx +2 -2
- package/docs/content/locales/zh-CN/skills-guide.mdx +1 -1
- package/docs/content/locales/zh-CN/template-assets.mdx +1 -1
- package/docs/content/locales/zh-CN/template-dispatch.mdx +2 -2
- package/docs/content/locales/zh-CN/template-plan.mdx +3 -3
- package/docs/content/locales/zh-TW/actions.mdx +1 -1
- package/docs/content/locales/zh-TW/authentication.mdx +1 -1
- package/docs/content/locales/zh-TW/dispatch.mdx +3 -3
- package/docs/content/locales/zh-TW/external-agents.mdx +23 -19
- package/docs/content/locales/zh-TW/mcp-clients.mdx +28 -3
- package/docs/content/locales/zh-TW/mcp-protocol.mdx +30 -15
- package/docs/content/locales/zh-TW/plan-plugin.mdx +3 -3
- package/docs/content/locales/zh-TW/server.mdx +2 -2
- package/docs/content/locales/zh-TW/skills-guide.mdx +1 -1
- package/docs/content/locales/zh-TW/template-assets.mdx +1 -1
- package/docs/content/locales/zh-TW/template-dispatch.mdx +2 -2
- package/docs/content/locales/zh-TW/template-plan.mdx +3 -3
- package/docs/content/mcp-clients.mdx +31 -4
- package/docs/content/mcp-protocol.mdx +35 -15
- package/docs/content/plan-plugin.mdx +3 -3
- package/docs/content/server.mdx +2 -2
- package/docs/content/skills-guide.mdx +1 -1
- package/docs/content/template-assets.mdx +1 -1
- package/docs/content/template-dispatch.mdx +2 -2
- package/docs/content/template-plan.mdx +3 -3
- package/package.json +2 -2
- package/src/templates/default/.agents/skills/security/SKILL.md +10 -0
- package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +15 -6
- package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +16 -10
- package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +20 -1
- package/src/templates/workspace-core/.agents/skills/security/SKILL.md +10 -0
|
@@ -260,6 +260,7 @@ export function useMeetingTranscription({
|
|
|
260
260
|
try {
|
|
261
261
|
const result = await callClipsAction<{
|
|
262
262
|
meetingId?: string;
|
|
263
|
+
scheduledEnd?: string | null;
|
|
263
264
|
recording?: { id?: string | null } | null;
|
|
264
265
|
}>("start-meeting-recording", { meetingId });
|
|
265
266
|
const resolvedMeetingId = result.meetingId ?? meetingId;
|
|
@@ -268,6 +269,13 @@ export function useMeetingTranscription({
|
|
|
268
269
|
throw new Error("Could not create a transcript session.");
|
|
269
270
|
}
|
|
270
271
|
|
|
272
|
+
const parsedScheduledEndMs = result.scheduledEnd
|
|
273
|
+
? Date.parse(result.scheduledEnd)
|
|
274
|
+
: Number.NaN;
|
|
275
|
+
const scheduledEndMs = Number.isFinite(parsedScheduledEndMs)
|
|
276
|
+
? parsedScheduledEndMs
|
|
277
|
+
: null;
|
|
278
|
+
|
|
271
279
|
const session: MeetingTranscriptionSession = {
|
|
272
280
|
meetingId: resolvedMeetingId,
|
|
273
281
|
recordingId,
|
|
@@ -366,6 +374,7 @@ export function useMeetingTranscription({
|
|
|
366
374
|
silenceThreshold: 0.05,
|
|
367
375
|
silenceMs: 15 * 60 * 1000,
|
|
368
376
|
callEndedMs: 2 * 60 * 1000,
|
|
377
|
+
scheduledEndMs,
|
|
369
378
|
watchSleep: true,
|
|
370
379
|
watchCallEnded: true,
|
|
371
380
|
};
|
|
@@ -81,6 +81,7 @@ import {
|
|
|
81
81
|
type CapturedTranscript,
|
|
82
82
|
type TranscriptionCapture,
|
|
83
83
|
} from "./transcription-capture";
|
|
84
|
+
import { shouldResampleVideoForUpload } from "./upload-video-stream";
|
|
84
85
|
|
|
85
86
|
export type { LocalExportedFile } from "./local-export";
|
|
86
87
|
export { planNativeFullscreenWarmOverlap } from "./native-recording-warm";
|
|
@@ -98,7 +99,7 @@ export interface RegionCaptureRect {
|
|
|
98
99
|
const NATIVE_FULLSCREEN_RECORDING_FLAG = "clips:native-fullscreen-recording";
|
|
99
100
|
const DEV_SYNTHETIC_CAPTURE_FLAG = "clips:dev-synthetic-capture";
|
|
100
101
|
const LEGACY_DEV_REAL_CAPTURE_FLAG = "clips:dev-real-capture";
|
|
101
|
-
const LIVE_UPLOAD_CHUNK_MS =
|
|
102
|
+
const LIVE_UPLOAD_CHUNK_MS = 2_000;
|
|
102
103
|
const NATIVE_FULLSCREEN_SEGMENT_MS = 5 * 60_000;
|
|
103
104
|
const NATIVE_FULLSCREEN_MIME_TYPE = "video/mp4";
|
|
104
105
|
// GCS resumable uploads require every non-final chunk to be a multiple of
|
|
@@ -302,6 +303,11 @@ function createUploadOptimizedVideoStream(
|
|
|
302
303
|
}
|
|
303
304
|
|
|
304
305
|
const sourceSize = videoTrackDimensions(source);
|
|
306
|
+
if (
|
|
307
|
+
!shouldResampleVideoForUpload(sourceSize, CLOUD_RECORDING_MAX_LONG_EDGE)
|
|
308
|
+
) {
|
|
309
|
+
return { stream: source, cleanup() {} };
|
|
310
|
+
}
|
|
305
311
|
const initial = scaledVideoDimensions(
|
|
306
312
|
sourceSize.width ?? 1280,
|
|
307
313
|
sourceSize.height ?? 720,
|
|
@@ -3216,8 +3222,8 @@ async function startRecordingInner(
|
|
|
3216
3222
|
// resumable session with the correct content type when the server supports
|
|
3217
3223
|
// streaming uploads.
|
|
3218
3224
|
const mimeCandidates = [
|
|
3219
|
-
"video/webm;codecs=vp9,opus",
|
|
3220
3225
|
"video/webm;codecs=vp8,opus",
|
|
3226
|
+
"video/webm;codecs=vp9,opus",
|
|
3221
3227
|
"video/webm",
|
|
3222
3228
|
];
|
|
3223
3229
|
const mimeType =
|
|
@@ -337,6 +337,10 @@ export async function startTranscriptionCapture(
|
|
|
337
337
|
mic,
|
|
338
338
|
captureSystem,
|
|
339
339
|
voiceProcessing: opts?.voiceProcessing,
|
|
340
|
+
// Recordings only persist final segments. Meetings use the same engine
|
|
341
|
+
// directly and retain live partials, but repeatedly inferring partials
|
|
342
|
+
// here burns CPU without any recording UI consuming them.
|
|
343
|
+
emitPartials: false,
|
|
340
344
|
});
|
|
341
345
|
console.log(
|
|
342
346
|
`[clips-recorder] transcription started (${engine} mic${captureSystem ? "+system" : ""})`,
|
|
@@ -367,6 +371,7 @@ export async function startTranscriptionCapture(
|
|
|
367
371
|
mic,
|
|
368
372
|
captureSystem,
|
|
369
373
|
voiceProcessing: opts?.voiceProcessing,
|
|
374
|
+
emitPartials: false,
|
|
370
375
|
});
|
|
371
376
|
// stop()/cancel() can run during the await above; if it did, the new
|
|
372
377
|
// engine would leak (mic/system capture stays live). Tear it down.
|
|
@@ -30,6 +30,9 @@ export interface SourcedTranscriptSegment extends TranscriptSegment {
|
|
|
30
30
|
source: TranscriptSource;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
const DUPLICATE_TOKEN_OVERLAP = 0.72;
|
|
34
|
+
const DUPLICATE_TIME_OVERLAP = 0.35;
|
|
35
|
+
|
|
33
36
|
export interface FinalTranscriptEvent {
|
|
34
37
|
/** Raw text (not trimmed); callers decide whether to skip empties. */
|
|
35
38
|
text: string;
|
|
@@ -70,6 +73,97 @@ export function speakerFor(
|
|
|
70
73
|
return source === "system" ? "Them" : "Me";
|
|
71
74
|
}
|
|
72
75
|
|
|
76
|
+
function normalizedTranscriptText(text: string): string {
|
|
77
|
+
return text
|
|
78
|
+
.normalize("NFKC")
|
|
79
|
+
.toLocaleLowerCase()
|
|
80
|
+
.replace(/[^\p{L}\p{N}]+/gu, " ")
|
|
81
|
+
.trim();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function transcriptWords(text: string): string[] {
|
|
85
|
+
const normalized = normalizedTranscriptText(text);
|
|
86
|
+
return normalized ? normalized.split(/\s+/) : [];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function tokenOverlap(left: string[], right: string[]): number {
|
|
90
|
+
if (left.length === 0 || right.length === 0) return 0;
|
|
91
|
+
|
|
92
|
+
const rightWords = new Set(right);
|
|
93
|
+
const sharedWords = new Set(left.filter((word) => rightWords.has(word)));
|
|
94
|
+
return sharedWords.size / Math.min(new Set(left).size, new Set(right).size);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function timeOverlapRatio(
|
|
98
|
+
left: SourcedTranscriptSegment,
|
|
99
|
+
right: SourcedTranscriptSegment,
|
|
100
|
+
): number {
|
|
101
|
+
const overlapStart = Math.max(left.startMs, right.startMs);
|
|
102
|
+
const overlapEnd = Math.min(left.endMs, right.endMs);
|
|
103
|
+
const overlapMs = Math.max(0, overlapEnd - overlapStart);
|
|
104
|
+
const shorterDuration = Math.max(
|
|
105
|
+
1,
|
|
106
|
+
Math.min(left.endMs - left.startMs, right.endMs - right.startMs),
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
return overlapMs / shorterDuration;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function isDuplicateTranscriptSegment(
|
|
113
|
+
existing: SourcedTranscriptSegment,
|
|
114
|
+
incoming: SourcedTranscriptSegment,
|
|
115
|
+
): boolean {
|
|
116
|
+
if (existing.source === incoming.source) return false;
|
|
117
|
+
|
|
118
|
+
const existingText = normalizedTranscriptText(existing.text);
|
|
119
|
+
const incomingText = normalizedTranscriptText(incoming.text);
|
|
120
|
+
const existingWords = transcriptWords(existing.text);
|
|
121
|
+
const incomingWords = transcriptWords(incoming.text);
|
|
122
|
+
|
|
123
|
+
if (
|
|
124
|
+
!existingText ||
|
|
125
|
+
!incomingText ||
|
|
126
|
+
existingWords.length < 3 ||
|
|
127
|
+
incomingWords.length < 3
|
|
128
|
+
) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (timeOverlapRatio(existing, incoming) < DUPLICATE_TIME_OVERLAP) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
existingText === incomingText ||
|
|
138
|
+
tokenOverlap(existingWords, incomingWords) >= DUPLICATE_TOKEN_OVERLAP
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function isDuplicateTranscriptLine(
|
|
143
|
+
lines: string[],
|
|
144
|
+
source: TranscriptSource,
|
|
145
|
+
text: string,
|
|
146
|
+
): boolean {
|
|
147
|
+
const words = transcriptWords(text);
|
|
148
|
+
if (words.length < 4) return false;
|
|
149
|
+
|
|
150
|
+
const speaker = speakerFor(source);
|
|
151
|
+
return lines.some((line) => {
|
|
152
|
+
const separatorIndex = line.indexOf(":");
|
|
153
|
+
if (separatorIndex === -1 || line.slice(0, separatorIndex) === speaker) {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const existingText = line.slice(separatorIndex + 1);
|
|
158
|
+
const existingWords = transcriptWords(existingText);
|
|
159
|
+
return (
|
|
160
|
+
normalizedTranscriptText(existingText) ===
|
|
161
|
+
normalizedTranscriptText(text) ||
|
|
162
|
+
tokenOverlap(existingWords, words) >= DUPLICATE_TOKEN_OVERLAP
|
|
163
|
+
);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
73
167
|
/**
|
|
74
168
|
* Fold a final-transcript event into a running transcript: appends a
|
|
75
169
|
* speaker-labelled line and the event's (non-empty) segments tagged with the
|
|
@@ -83,14 +177,39 @@ export function appendFinalTranscript(
|
|
|
83
177
|
): boolean {
|
|
84
178
|
const text = event.text.trim();
|
|
85
179
|
if (!text) return false;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
180
|
+
|
|
181
|
+
if (event.segments.length === 0) {
|
|
182
|
+
if (isDuplicateTranscriptLine(lines, event.source, text)) return false;
|
|
183
|
+
|
|
184
|
+
lines.push(`${speakerFor(event.source)}: ${text}`);
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const uniqueSegments = event.segments.filter((segment) => {
|
|
189
|
+
const segText = segment.text?.trim();
|
|
190
|
+
if (!segText) return false;
|
|
191
|
+
|
|
192
|
+
return !segments.some((existing) =>
|
|
193
|
+
isDuplicateTranscriptSegment(existing, {
|
|
194
|
+
...segment,
|
|
195
|
+
text: segText,
|
|
196
|
+
source: event.source,
|
|
197
|
+
}),
|
|
198
|
+
);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
if (uniqueSegments.length === 0) return false;
|
|
202
|
+
|
|
203
|
+
lines.push(
|
|
204
|
+
`${speakerFor(event.source)}: ${uniqueSegments
|
|
205
|
+
.map((segment) => segment.text.trim())
|
|
206
|
+
.join(" ")}`,
|
|
207
|
+
);
|
|
208
|
+
for (const seg of uniqueSegments) {
|
|
90
209
|
segments.push({
|
|
91
210
|
startMs: seg.startMs,
|
|
92
211
|
endMs: seg.endMs,
|
|
93
|
-
text:
|
|
212
|
+
text: seg.text.trim(),
|
|
94
213
|
source: event.source,
|
|
95
214
|
});
|
|
96
215
|
}
|
|
@@ -120,6 +239,7 @@ export async function restartTranscriptionEngine(
|
|
|
120
239
|
mic?: MicSelection,
|
|
121
240
|
captureSystem: boolean = true,
|
|
122
241
|
voiceProcessing: boolean = false,
|
|
242
|
+
emitPartials: boolean = true,
|
|
123
243
|
): Promise<void> {
|
|
124
244
|
if (engine === "whisper") {
|
|
125
245
|
await invoke("audio_transcription_start", {
|
|
@@ -129,6 +249,7 @@ export async function restartTranscriptionEngine(
|
|
|
129
249
|
micDeviceLabel: mic?.label || null,
|
|
130
250
|
captureSystem,
|
|
131
251
|
voiceProcessing,
|
|
252
|
+
emitPartials,
|
|
132
253
|
owner: "meeting",
|
|
133
254
|
});
|
|
134
255
|
} else {
|
|
@@ -157,15 +278,23 @@ export async function startTranscriptionEngine(opts: {
|
|
|
157
278
|
* only when combined ScreenCaptureKit capture is unavailable or fails.
|
|
158
279
|
*/
|
|
159
280
|
voiceProcessing?: boolean;
|
|
281
|
+
/**
|
|
282
|
+
* Emit recurring live partial transcripts while speech is in progress.
|
|
283
|
+
* Meetings render these updates; recordings only persist final segments and
|
|
284
|
+
* disable them to avoid repeatedly transcribing the same growing buffer.
|
|
285
|
+
*/
|
|
286
|
+
emitPartials?: boolean;
|
|
160
287
|
}): Promise<TranscriptionEngine> {
|
|
161
288
|
const captureSystem = opts.captureSystem ?? true;
|
|
162
289
|
const voiceProcessing = opts.voiceProcessing ?? false;
|
|
290
|
+
const emitPartials = opts.emitPartials ?? true;
|
|
163
291
|
try {
|
|
164
292
|
await restartTranscriptionEngine(
|
|
165
293
|
"whisper",
|
|
166
294
|
opts.mic,
|
|
167
295
|
captureSystem,
|
|
168
296
|
voiceProcessing,
|
|
297
|
+
emitPartials,
|
|
169
298
|
);
|
|
170
299
|
return "whisper";
|
|
171
300
|
} catch (err) {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface VideoDimensions {
|
|
2
|
+
width: number | null;
|
|
3
|
+
height: number | null;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function isPositiveNumber(value: number | null): value is number {
|
|
7
|
+
return value !== null && Number.isFinite(value) && value > 0;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Whether upload capture needs a canvas-backed resize pass.
|
|
12
|
+
*
|
|
13
|
+
* Unknown dimensions stay on the defensive resize path. A source that is
|
|
14
|
+
* already within the upload budget can go straight to MediaRecorder, avoiding
|
|
15
|
+
* a full-frame draw on the renderer thread for every captured frame.
|
|
16
|
+
*/
|
|
17
|
+
export function shouldResampleVideoForUpload(
|
|
18
|
+
dimensions: VideoDimensions,
|
|
19
|
+
maxLongEdge: number,
|
|
20
|
+
): boolean {
|
|
21
|
+
if (
|
|
22
|
+
!isPositiveNumber(dimensions.width) ||
|
|
23
|
+
!isPositiveNumber(dimensions.height)
|
|
24
|
+
) {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
return Math.max(dimensions.width, dimensions.height) > maxLongEdge;
|
|
28
|
+
}
|
|
@@ -83,8 +83,17 @@ export function FlowBar() {
|
|
|
83
83
|
const BAR_COUNT = 14;
|
|
84
84
|
const BAR_WIDTH = 2;
|
|
85
85
|
const BAR_GAP = 3;
|
|
86
|
+
// A bar waveform reads the same well below display refresh rate
|
|
87
|
+
// (60-120Hz); cap the actual draw work to ~20fps while still scheduling
|
|
88
|
+
// via rAF every frame so the loop still pauses when the bar is hidden.
|
|
89
|
+
const FRAME_INTERVAL_MS = 1000 / 20;
|
|
90
|
+
let lastDrawMs = 0;
|
|
91
|
+
|
|
92
|
+
function draw(timestamp: number) {
|
|
93
|
+
rafRef.current = requestAnimationFrame(draw);
|
|
94
|
+
if (timestamp - lastDrawMs < FRAME_INTERVAL_MS) return;
|
|
95
|
+
lastDrawMs = timestamp;
|
|
86
96
|
|
|
87
|
-
function draw() {
|
|
88
97
|
const canvas = canvasRef.current;
|
|
89
98
|
if (!canvas) return;
|
|
90
99
|
const ctx = canvas.getContext("2d");
|
|
@@ -119,8 +128,6 @@ export function FlowBar() {
|
|
|
119
128
|
ctx.roundRect(x, y, BAR_WIDTH, h, 1);
|
|
120
129
|
ctx.fill();
|
|
121
130
|
}
|
|
122
|
-
|
|
123
|
-
rafRef.current = requestAnimationFrame(draw);
|
|
124
131
|
}
|
|
125
132
|
|
|
126
133
|
rafRef.current = requestAnimationFrame(draw);
|
|
@@ -128,6 +128,16 @@ export function MeetingNotification() {
|
|
|
128
128
|
const [pending, setPending] = useState(false);
|
|
129
129
|
const autoHideTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
130
130
|
const dataRef = useRef<NotificationData | null>(null);
|
|
131
|
+
// Real DOM hover only fires while this overlay window is key, which macOS
|
|
132
|
+
// won't grant it without a click (`show_without_activation` never
|
|
133
|
+
// activates). `polledHovered` mirrors the Rust-side global cursor poll
|
|
134
|
+
// (`meetings:notification-hover`, see `start_meeting_notification_hover_tracking`
|
|
135
|
+
// in notifications.rs) so the X still reveals on hover while another app is
|
|
136
|
+
// focused — same fallback pattern as the recording pill's `clips:pill-hover`.
|
|
137
|
+
const [domHovered, setDomHovered] = useState(false);
|
|
138
|
+
const [polledHovered, setPolledHovered] = useState(false);
|
|
139
|
+
const hovered = domHovered || polledHovered;
|
|
140
|
+
const prevHoveredRef = useRef(false);
|
|
131
141
|
|
|
132
142
|
useEffect(() => {
|
|
133
143
|
dataRef.current = data;
|
|
@@ -150,6 +160,30 @@ export function MeetingNotification() {
|
|
|
150
160
|
}
|
|
151
161
|
}, [data]);
|
|
152
162
|
|
|
163
|
+
useEffect(() => {
|
|
164
|
+
if (!data) {
|
|
165
|
+
// Dismissing doesn't guarantee mouseleave/hovered:false fires first
|
|
166
|
+
// (e.g. dismissed while the cursor is still over the card), so clear
|
|
167
|
+
// every hover source here — otherwise the next notification can
|
|
168
|
+
// inherit hovered === true and open with its close button already
|
|
169
|
+
// showing and auto-hide already cancelled.
|
|
170
|
+
prevHoveredRef.current = false;
|
|
171
|
+
setDomHovered(false);
|
|
172
|
+
setPolledHovered(false);
|
|
173
|
+
setShowClose(false);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (hovered === prevHoveredRef.current) return;
|
|
177
|
+
prevHoveredRef.current = hovered;
|
|
178
|
+
setShowClose(hovered);
|
|
179
|
+
if (hovered) {
|
|
180
|
+
clearAutoHide();
|
|
181
|
+
} else {
|
|
182
|
+
setMenuOpen(false);
|
|
183
|
+
resumeAutoHide();
|
|
184
|
+
}
|
|
185
|
+
}, [data, hovered]);
|
|
186
|
+
|
|
153
187
|
function showNotification(
|
|
154
188
|
payload: NotificationData,
|
|
155
189
|
options?: { hydrated?: boolean },
|
|
@@ -191,6 +225,12 @@ export function MeetingNotification() {
|
|
|
191
225
|
}),
|
|
192
226
|
);
|
|
193
227
|
|
|
228
|
+
trackListen(
|
|
229
|
+
listen<{ hovered: boolean }>("meetings:notification-hover", (ev) => {
|
|
230
|
+
setPolledHovered(ev.payload.hovered);
|
|
231
|
+
}),
|
|
232
|
+
);
|
|
233
|
+
|
|
194
234
|
// Cold overlay boot: hydrate any payload stored before this webview
|
|
195
235
|
// mounted (calendar or adhoc).
|
|
196
236
|
invoke<NotificationData | null>("take_pending_meeting_notification")
|
|
@@ -329,15 +369,8 @@ export function MeetingNotification() {
|
|
|
329
369
|
<div className="meeting-notification-root">
|
|
330
370
|
<div
|
|
331
371
|
className="meeting-notification"
|
|
332
|
-
onMouseEnter={() =>
|
|
333
|
-
|
|
334
|
-
clearAutoHide();
|
|
335
|
-
}}
|
|
336
|
-
onMouseLeave={() => {
|
|
337
|
-
setShowClose(false);
|
|
338
|
-
setMenuOpen(false);
|
|
339
|
-
resumeAutoHide();
|
|
340
|
-
}}
|
|
372
|
+
onMouseEnter={() => setDomHovered(true)}
|
|
373
|
+
onMouseLeave={() => setDomHovered(false)}
|
|
341
374
|
>
|
|
342
375
|
<div
|
|
343
376
|
className={`meeting-notification-bar ${isCalendar ? "meeting-notification-bar-calendar" : "meeting-notification-bar-adhoc"}`}
|
|
@@ -352,9 +352,18 @@ export function RecordingPill() {
|
|
|
352
352
|
);
|
|
353
353
|
|
|
354
354
|
const startMs = Date.now();
|
|
355
|
+
let lastDrawMs = 0;
|
|
356
|
+
// A bar meter reads the same to the eye well below display refresh rate
|
|
357
|
+
// (60-120Hz); cap the actual draw work to ~20fps while still scheduling
|
|
358
|
+
// via rAF every frame so the loop still pauses when the pill is hidden.
|
|
359
|
+
const FRAME_INTERVAL_MS = 1000 / 20;
|
|
355
360
|
const tick = () => {
|
|
361
|
+
rafRef.current = requestAnimationFrame(tick);
|
|
362
|
+
const nowMs = Date.now();
|
|
363
|
+
if (nowMs - lastDrawMs < FRAME_INTERVAL_MS) return;
|
|
364
|
+
lastDrawMs = nowMs;
|
|
356
365
|
// Modulo prevents float precision loss on long recordings.
|
|
357
|
-
const t = (
|
|
366
|
+
const t = (nowMs - startMs) % 1_000_000;
|
|
358
367
|
for (const s of setups) {
|
|
359
368
|
const target = Math.min(1, s.levelRef.current * s.gain);
|
|
360
369
|
|
|
@@ -385,7 +394,6 @@ export function RecordingPill() {
|
|
|
385
394
|
}
|
|
386
395
|
s.ctx2d.shadowBlur = 0;
|
|
387
396
|
}
|
|
388
|
-
rafRef.current = requestAnimationFrame(tick);
|
|
389
397
|
};
|
|
390
398
|
tick();
|
|
391
399
|
return () => {
|
|
@@ -124,7 +124,12 @@ screencapturekit = { version = "2.0.0", features = ["macos_15_0"] }
|
|
|
124
124
|
# AudioBufferList type so we can hand SCK's CMSampleBuffer audio bytes to
|
|
125
125
|
# AVAudioPCMBuffer for the speech recognizer.
|
|
126
126
|
objc2-core-audio-types = "0.3"
|
|
127
|
-
whisper-
|
|
127
|
+
# `metal` builds whisper.cpp's ggml-metal backend and links it in (the sys
|
|
128
|
+
# crate's build script embeds the compiled metallib, so no app-bundle/runtime
|
|
129
|
+
# asset changes are needed). Without it, whisper.cpp decode runs CPU-only.
|
|
130
|
+
# `use_gpu` is still set explicitly per-arch in whisper_speech.rs so Intel
|
|
131
|
+
# Macs don't exercise Metal even though the feature is compiled in.
|
|
132
|
+
whisper-rs = { version = "0.16.0", features = ["metal"] }
|
|
128
133
|
# NOTE: We hand-roll the few EventKit selectors we need via raw `objc2`
|
|
129
134
|
# msg_send! in `eventkit.rs` rather than depending on the `objc2-event-kit`
|
|
130
135
|
# crate. Its API surface drifts between minor 0.3.x releases (and not
|
|
@@ -6,8 +6,13 @@
|
|
|
6
6
|
|
|
7
7
|
use serde::{Deserialize, Serialize};
|
|
8
8
|
use serde_json::Value;
|
|
9
|
+
use std::sync::atomic::{AtomicBool, Ordering};
|
|
9
10
|
use std::sync::Mutex;
|
|
10
|
-
use
|
|
11
|
+
use std::time::Duration;
|
|
12
|
+
use tauri::{
|
|
13
|
+
AppHandle, Emitter, Manager, PhysicalPosition, PhysicalSize, WebviewWindow,
|
|
14
|
+
WebviewWindowBuilder,
|
|
15
|
+
};
|
|
11
16
|
|
|
12
17
|
use crate::dlog;
|
|
13
18
|
use crate::util::{
|
|
@@ -54,6 +59,75 @@ fn notification_rect(app: &AppHandle) -> (u32, u32, i32, i32) {
|
|
|
54
59
|
(w, h, x, top.max(0))
|
|
55
60
|
}
|
|
56
61
|
|
|
62
|
+
static MEETING_NOTIF_HOVER_TRACKING: AtomicBool = AtomicBool::new(false);
|
|
63
|
+
|
|
64
|
+
/// True when the global cursor sits inside the notification window's frame.
|
|
65
|
+
/// Mirrors `cursor_inside_pill_frame` in `recording_indicator.rs`: cursor and
|
|
66
|
+
/// frame both come from Tauri (physical px, desktop top-left origin), so the
|
|
67
|
+
/// test is a plain point-in-rect with no AppKit hop.
|
|
68
|
+
fn cursor_inside_notification_frame(window: &WebviewWindow) -> bool {
|
|
69
|
+
let (Ok(c), Ok(p), Ok(s)) = (
|
|
70
|
+
window.cursor_position(),
|
|
71
|
+
window.outer_position(),
|
|
72
|
+
window.outer_size(),
|
|
73
|
+
) else {
|
|
74
|
+
return false;
|
|
75
|
+
};
|
|
76
|
+
c.x >= p.x as f64
|
|
77
|
+
&& c.x <= (p.x + s.width as i32) as f64
|
|
78
|
+
&& c.y >= p.y as f64
|
|
79
|
+
&& c.y <= (p.y + s.height as i32) as f64
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/// Poll the cursor against the notification frame and emit
|
|
83
|
+
/// `meetings:notification-hover` on transitions. The window never becomes key
|
|
84
|
+
/// (`show_without_activation` uses `orderFrontRegardless`, not
|
|
85
|
+
/// `makeKeyAndOrderFront:`), so CSS `:hover`/`onMouseEnter` only fires once
|
|
86
|
+
/// the user's first click makes it key — this poll is the fallback that
|
|
87
|
+
/// reveals the close button on real hover before that click, same pattern as
|
|
88
|
+
/// `start_pill_hover_tracking`. Idempotent — a second call is a no-op while a
|
|
89
|
+
/// loop is already running.
|
|
90
|
+
fn start_meeting_notification_hover_tracking(app: &AppHandle) {
|
|
91
|
+
if MEETING_NOTIF_HOVER_TRACKING.swap(true, Ordering::SeqCst) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
let app = app.clone();
|
|
95
|
+
tauri::async_runtime::spawn(async move {
|
|
96
|
+
let mut prev = false;
|
|
97
|
+
while MEETING_NOTIF_HOVER_TRACKING.load(Ordering::Relaxed) {
|
|
98
|
+
let Some(win) = app.get_webview_window(MEETING_NOTIFICATION_LABEL) else {
|
|
99
|
+
break;
|
|
100
|
+
};
|
|
101
|
+
// The window is reused across notifications (hidden/shown from
|
|
102
|
+
// the frontend, never destroyed), so this loop runs for the rest
|
|
103
|
+
// of the app session. Skip the cursor/frame queries entirely
|
|
104
|
+
// while hidden — no notification is on screen to hover — and
|
|
105
|
+
// back off to a slower idle tick until it's shown again.
|
|
106
|
+
if !win.is_visible().unwrap_or(false) {
|
|
107
|
+
if prev {
|
|
108
|
+
prev = false;
|
|
109
|
+
let _ = win.emit(
|
|
110
|
+
"meetings:notification-hover",
|
|
111
|
+
serde_json::json!({ "hovered": false }),
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
tokio::time::sleep(Duration::from_millis(250)).await;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
let inside = cursor_inside_notification_frame(&win);
|
|
118
|
+
if inside != prev {
|
|
119
|
+
prev = inside;
|
|
120
|
+
let _ = win.emit(
|
|
121
|
+
"meetings:notification-hover",
|
|
122
|
+
serde_json::json!({ "hovered": inside }),
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
tokio::time::sleep(Duration::from_millis(80)).await;
|
|
126
|
+
}
|
|
127
|
+
MEETING_NOTIF_HOVER_TRACKING.store(false, Ordering::SeqCst);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
57
131
|
pub fn show_meeting_notification_window(app: &AppHandle) -> Result<(), String> {
|
|
58
132
|
let (w, h, x, y) = notification_rect(app);
|
|
59
133
|
if let Some(existing) = app.get_webview_window(MEETING_NOTIFICATION_LABEL) {
|
|
@@ -61,6 +135,7 @@ pub fn show_meeting_notification_window(app: &AppHandle) -> Result<(), String> {
|
|
|
61
135
|
let _ = existing.set_position(PhysicalPosition::new(x, y));
|
|
62
136
|
configure_overlay_behavior(&existing);
|
|
63
137
|
show_without_activation(&existing);
|
|
138
|
+
start_meeting_notification_hover_tracking(&app);
|
|
64
139
|
return Ok(());
|
|
65
140
|
}
|
|
66
141
|
|
|
@@ -97,6 +172,7 @@ pub fn show_meeting_notification_window(app: &AppHandle) -> Result<(), String> {
|
|
|
97
172
|
// own recording chrome is still excluded elsewhere so it won't leak.)
|
|
98
173
|
configure_overlay_behavior(&win);
|
|
99
174
|
show_without_activation(&win);
|
|
175
|
+
start_meeting_notification_hover_tracking(&app);
|
|
100
176
|
Ok(())
|
|
101
177
|
}
|
|
102
178
|
|