From 3b474ba1c028098b659f49e6469a51333ed0a082 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Thu, 16 Apr 2026 18:15:06 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F(backend)=20control=20metadat?= =?UTF-8?q?a=20collector=20agent=20launch=20via=20feature=20flag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow controlling when the metadata collector agent is started, enabling users to try the feature and disable it if needed. Introduce a user-level feature flag to toggle the agent for the initial release. --- src/backend/core/api/serializers.py | 3 +++ src/backend/core/api/viewsets.py | 3 +-- src/backend/core/services/livekit_events.py | 4 +--- src/frontend/src/features/analytics/enums.ts | 1 + .../recording/components/TranscriptSidePanel.tsx | 4 ++++ .../recording/hooks/useMetadataCollectorEnabled.ts | 10 ++++++++++ 6 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 src/frontend/src/features/recording/hooks/useMetadataCollectorEnabled.ts diff --git a/src/backend/core/api/serializers.py b/src/backend/core/api/serializers.py index 3b84021a..0d03ace5 100644 --- a/src/backend/core/api/serializers.py +++ b/src/backend/core/api/serializers.py @@ -232,11 +232,14 @@ class RecordingOptions(BaseModel): When `None`, falls back to the application default. original_mode: The original recording mode before any override. Must be one of the valid RecordingModeChoices values when provided. + collect_metadata: Whether to collect additional metadata during recording. + When `None`, no metadata are collected. """ language: str | None = None transcribe: bool | None = None + collect_metadata: bool | None = None original_mode: Literal["screen_recording", "transcript"] | None = None model_config = {"extra": "forbid"} diff --git a/src/backend/core/api/viewsets.py b/src/backend/core/api/viewsets.py index a2eda72a..50b2efc4 100644 --- a/src/backend/core/api/viewsets.py +++ b/src/backend/core/api/viewsets.py @@ -343,8 +343,7 @@ class RoomViewSet( ) if settings.METADATA_COLLECTOR_ENABLED and ( - recording.mode == models.RecordingModeChoices.TRANSCRIPT - or recording.options.get("transcribe", False) + recording.options.get("collect_metadata", False) ): try: MetadataCollectorService().start(recording) diff --git a/src/backend/core/services/livekit_events.py b/src/backend/core/services/livekit_events.py index 4815a06b..e8a8822a 100644 --- a/src/backend/core/services/livekit_events.py +++ b/src/backend/core/services/livekit_events.py @@ -178,9 +178,7 @@ class LiveKitEventsService: except utils.MetadataUpdateException as e: logger.exception("Failed to update room's metadata: %s", e) - if settings.METADATA_COLLECTOR_ENABLED and recording.options.get( - "metadata_collector_dispatch_id" - ): + if recording.options.get("metadata_collector_dispatch_id", None) is not None: try: MetadataCollectorService().stop(recording) except MetadataCollectorException: diff --git a/src/frontend/src/features/analytics/enums.ts b/src/frontend/src/features/analytics/enums.ts index 0f6e4f5d..f8bfca66 100644 --- a/src/frontend/src/features/analytics/enums.ts +++ b/src/frontend/src/features/analytics/enums.ts @@ -5,4 +5,5 @@ export enum FeatureFlags { noiseReduction = 'noise-reduction', subtitles = 'subtitles', candidatePolling = 'candidate-polling', + metadataCollector = 'metadata-collector', } diff --git a/src/frontend/src/features/recording/components/TranscriptSidePanel.tsx b/src/frontend/src/features/recording/components/TranscriptSidePanel.tsx index b9d447f1..8090e0d3 100644 --- a/src/frontend/src/features/recording/components/TranscriptSidePanel.tsx +++ b/src/frontend/src/features/recording/components/TranscriptSidePanel.tsx @@ -32,6 +32,7 @@ import { NoAccessView } from './NoAccessView' import { ControlsButton } from './ControlsButton' import { RowWrapper } from './RowWrapper' import { useMutateRecording } from '../hooks/useMutateRecording' +import { useIsMetadataCollectorEnabled } from '../hooks/useMetadataCollectorEnabled' import { useSidePanel } from '@/features/rooms/livekit/hooks/useSidePanel' export const TranscriptSidePanel = () => { @@ -59,6 +60,8 @@ export const TranscriptSidePanel = () => { FeatureFlags.Transcript ) + const isMetadataCollectorEnabled = useIsMetadataCollectorEnabled() + const roomId = useRoomId() const { startRecording, isPendingToStart, stopRecording, isPendingToStop } = @@ -106,6 +109,7 @@ export const TranscriptSidePanel = () => { transcribe: true, original_mode: RecordingMode.Transcript, }), + collect_metadata: isMetadataCollectorEnabled, } await startRecording({ diff --git a/src/frontend/src/features/recording/hooks/useMetadataCollectorEnabled.ts b/src/frontend/src/features/recording/hooks/useMetadataCollectorEnabled.ts new file mode 100644 index 00000000..858c3557 --- /dev/null +++ b/src/frontend/src/features/recording/hooks/useMetadataCollectorEnabled.ts @@ -0,0 +1,10 @@ +import { useFeatureFlagEnabled } from 'posthog-js/react' +import { useIsAnalyticsEnabled } from '@/features/analytics/hooks/useIsAnalyticsEnabled' +import { FeatureFlags } from '@/features/analytics/enums' + +export const useIsMetadataCollectorEnabled = () => { + const featureEnabled = useFeatureFlagEnabled(FeatureFlags.metadataCollector) + const isAnalyticsEnabled = useIsAnalyticsEnabled() + + return (featureEnabled && isAnalyticsEnabled) || true +}