diff --git a/frontend/src/hooks/mutation/use-create-conversation.ts b/frontend/src/hooks/mutation/use-create-conversation.ts index a44d921e44..8f6df2c272 100644 --- a/frontend/src/hooks/mutation/use-create-conversation.ts +++ b/frontend/src/hooks/mutation/use-create-conversation.ts @@ -4,8 +4,8 @@ import V1ConversationService from "#/api/conversation-service/v1-conversation-se import { SuggestedTask } from "#/utils/types"; import { Provider } from "#/types/settings"; import { CreateMicroagent, Conversation } from "#/api/open-hands.types"; -import { USE_V1_CONVERSATION_API } from "#/utils/feature-flags"; import { useTracking } from "#/hooks/use-tracking"; +import { useSettings } from "#/hooks/query/use-settings"; interface CreateConversationVariables { query?: string; @@ -34,6 +34,7 @@ interface CreateConversationResponse extends Partial { export const useCreateConversation = () => { const queryClient = useQueryClient(); const { trackConversationCreated } = useTracking(); + const { data: settings } = useSettings(); return useMutation({ mutationKey: ["create-conversation"], @@ -50,7 +51,7 @@ export const useCreateConversation = () => { agentType, } = variables; - const useV1 = USE_V1_CONVERSATION_API() && !createMicroagent; + const useV1 = !!settings?.V1_ENABLED && !createMicroagent; if (useV1) { // Use V1 API - creates a conversation start task diff --git a/frontend/src/hooks/mutation/use-save-settings.ts b/frontend/src/hooks/mutation/use-save-settings.ts index c8a433e9dc..099ab41ea4 100644 --- a/frontend/src/hooks/mutation/use-save-settings.ts +++ b/frontend/src/hooks/mutation/use-save-settings.ts @@ -35,6 +35,7 @@ const saveSettingsMutationFn = async (settings: Partial) => { settings.GIT_USER_NAME?.trim() || DEFAULT_SETTINGS.GIT_USER_NAME, git_user_email: settings.GIT_USER_EMAIL?.trim() || DEFAULT_SETTINGS.GIT_USER_EMAIL, + v1_enabled: settings.V1_ENABLED, }; await SettingsService.saveSettings(apiSettings); diff --git a/frontend/src/hooks/query/use-settings.ts b/frontend/src/hooks/query/use-settings.ts index 74a516f4a6..c1769c8422 100644 --- a/frontend/src/hooks/query/use-settings.ts +++ b/frontend/src/hooks/query/use-settings.ts @@ -36,6 +36,7 @@ const getSettingsQueryFn = async (): Promise => { GIT_USER_EMAIL: apiSettings.git_user_email || DEFAULT_SETTINGS.GIT_USER_EMAIL, IS_NEW_USER: false, + V1_ENABLED: apiSettings.v1_enabled ?? DEFAULT_SETTINGS.V1_ENABLED, }; }; diff --git a/frontend/src/hooks/query/use-start-tasks.ts b/frontend/src/hooks/query/use-start-tasks.ts index 833ce86258..6af56f2296 100644 --- a/frontend/src/hooks/query/use-start-tasks.ts +++ b/frontend/src/hooks/query/use-start-tasks.ts @@ -1,6 +1,6 @@ import { useQuery } from "@tanstack/react-query"; import V1ConversationService from "#/api/conversation-service/v1-conversation-service.api"; -import { USE_V1_CONVERSATION_API } from "#/utils/feature-flags"; +import { useSettings } from "#/hooks/query/use-settings"; /** * Hook to fetch in-progress V1 conversation start tasks @@ -13,13 +13,17 @@ import { USE_V1_CONVERSATION_API } from "#/utils/feature-flags"; * @param limit Maximum number of tasks to return (max 100) * @returns Query result with array of in-progress start tasks */ -export const useStartTasks = (limit = 10) => - useQuery({ +export const useStartTasks = (limit = 10) => { + const { data: settings } = useSettings(); + const isV1Enabled = settings?.V1_ENABLED; + + return useQuery({ queryKey: ["start-tasks", "search", limit], queryFn: () => V1ConversationService.searchStartTasks(limit), - enabled: USE_V1_CONVERSATION_API(), + enabled: isV1Enabled, select: (tasks) => tasks.filter( (task) => task.status !== "READY" && task.status !== "ERROR", ), }); +}; diff --git a/frontend/src/routes/llm-settings.tsx b/frontend/src/routes/llm-settings.tsx index d78df48cd9..81c864fc25 100644 --- a/frontend/src/routes/llm-settings.tsx +++ b/frontend/src/routes/llm-settings.tsx @@ -28,7 +28,6 @@ import { KeyStatusIcon } from "#/components/features/settings/key-status-icon"; import { DEFAULT_SETTINGS } from "#/services/settings"; import { getProviderId } from "#/utils/map-provider"; import { DEFAULT_OPENHANDS_MODEL } from "#/utils/verified-models"; -import { USE_V1_CONVERSATION_API } from "#/utils/feature-flags"; interface OpenHandsApiKeyHelpProps { testId: string; @@ -119,8 +118,8 @@ function LlmSettingsScreen() { const isSaasMode = config?.APP_MODE === "saas"; const shouldUseOpenHandsKey = isOpenHandsProvider && isSaasMode; - // Determine if we should hide the agent dropdown when V1 conversation API feature flag is enabled - const isV1Enabled = USE_V1_CONVERSATION_API(); + // Determine if we should hide the agent dropdown when V1 conversation API is enabled + const isV1Enabled = settings?.V1_ENABLED; React.useEffect(() => { const determineWhetherToToggleAdvancedSettings = () => { diff --git a/frontend/src/services/settings.ts b/frontend/src/services/settings.ts index f7cad15b43..7c648247d6 100644 --- a/frontend/src/services/settings.ts +++ b/frontend/src/services/settings.ts @@ -31,6 +31,7 @@ export const DEFAULT_SETTINGS: Settings = { }, GIT_USER_NAME: "openhands", GIT_USER_EMAIL: "openhands@all-hands.dev", + V1_ENABLED: false, }; /** diff --git a/frontend/src/settings-service/settings.types.ts b/frontend/src/settings-service/settings.types.ts index bdd1610f49..c6d33a7ee5 100644 --- a/frontend/src/settings-service/settings.types.ts +++ b/frontend/src/settings-service/settings.types.ts @@ -35,6 +35,7 @@ export type ApiSettings = { email_verified?: boolean; git_user_name?: string; git_user_email?: string; + v1_enabled?: boolean; }; export type PostApiSettings = ApiSettings & { diff --git a/frontend/src/types/settings.ts b/frontend/src/types/settings.ts index f76fcaa19a..2299288132 100644 --- a/frontend/src/types/settings.ts +++ b/frontend/src/types/settings.ts @@ -63,6 +63,7 @@ export type Settings = { EMAIL_VERIFIED?: boolean; GIT_USER_NAME?: string; GIT_USER_EMAIL?: string; + V1_ENABLED?: boolean; }; export type PostSettings = Settings & { diff --git a/frontend/src/utils/feature-flags.ts b/frontend/src/utils/feature-flags.ts index acbe83d7d7..0f38a4d7ea 100644 --- a/frontend/src/utils/feature-flags.ts +++ b/frontend/src/utils/feature-flags.ts @@ -17,6 +17,4 @@ export const HIDE_LLM_SETTINGS = () => loadFeatureFlag("HIDE_LLM_SETTINGS"); export const VSCODE_IN_NEW_TAB = () => loadFeatureFlag("VSCODE_IN_NEW_TAB"); export const ENABLE_TRAJECTORY_REPLAY = () => loadFeatureFlag("TRAJECTORY_REPLAY"); -export const USE_V1_CONVERSATION_API = () => - loadFeatureFlag("USE_V1_CONVERSATION_API"); export const USE_PLANNING_AGENT = () => loadFeatureFlag("USE_PLANNING_AGENT"); diff --git a/openhands/storage/data_models/settings.py b/openhands/storage/data_models/settings.py index 6e2f6038c3..0dc9b99e62 100644 --- a/openhands/storage/data_models/settings.py +++ b/openhands/storage/data_models/settings.py @@ -1,5 +1,7 @@ from __future__ import annotations +import os + from pydantic import ( BaseModel, ConfigDict, @@ -48,7 +50,7 @@ class Settings(BaseModel): email_verified: bool | None = None git_user_name: str | None = None git_user_email: str | None = None - v1_enabled: bool | None = None + v1_enabled: bool | None = Field(default=bool(os.getenv('V1_ENABLED') == '1')) model_config = ConfigDict( validate_assignment=True,