mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
[Feat]: Per user proactive conversation starters for cloud openhands (#8272)
Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
parent
24ffd14f14
commit
4c1ae6fd8d
@ -20,6 +20,8 @@ const saveSettingsMutationFn = async (settings: Partial<PostSettings>) => {
|
||||
enable_default_condenser: settings.ENABLE_DEFAULT_CONDENSER,
|
||||
enable_sound_notifications: settings.ENABLE_SOUND_NOTIFICATIONS,
|
||||
user_consents_to_analytics: settings.user_consents_to_analytics,
|
||||
enable_proactive_conversation_starters:
|
||||
settings.ENABLE_PROACTIVE_CONVERSATION_STARTERS,
|
||||
};
|
||||
|
||||
await OpenHands.saveSettings(apiSettings);
|
||||
|
||||
@ -22,6 +22,8 @@ const getSettingsQueryFn = async (): Promise<Settings> => {
|
||||
PROVIDER_TOKENS_SET: apiSettings.provider_tokens_set,
|
||||
ENABLE_DEFAULT_CONDENSER: apiSettings.enable_default_condenser,
|
||||
ENABLE_SOUND_NOTIFICATIONS: apiSettings.enable_sound_notifications,
|
||||
ENABLE_PROACTIVE_CONVERSATION_STARTERS:
|
||||
apiSettings.enable_proactive_conversation_starters,
|
||||
USER_CONSENTS_TO_ANALYTICS: apiSettings.user_consents_to_analytics,
|
||||
IS_NEW_USER: false,
|
||||
};
|
||||
|
||||
@ -70,6 +70,7 @@ export enum I18nKey {
|
||||
SETTINGS$LLM_SETTINGS = "SETTINGS$LLM_SETTINGS",
|
||||
SETTINGS$GIT_SETTINGS = "SETTINGS$GIT_SETTINGS",
|
||||
SETTINGS$SOUND_NOTIFICATIONS = "SETTINGS$SOUND_NOTIFICATIONS",
|
||||
SETTINGS$PROACTIVE_CONVERSATION_STARTERS = "SETTINGS$PROACTIVE_CONVERSATION_STARTERS",
|
||||
SETTINGS$CUSTOM_MODEL = "SETTINGS$CUSTOM_MODEL",
|
||||
GITHUB$CODE_NOT_IN_GITHUB = "GITHUB$CODE_NOT_IN_GITHUB",
|
||||
GITHUB$START_FROM_SCRATCH = "GITHUB$START_FROM_SCRATCH",
|
||||
|
||||
@ -1052,6 +1052,21 @@
|
||||
"fr": "Notifications sonores",
|
||||
"tr": "Ses Bildirimleri"
|
||||
},
|
||||
"SETTINGS$PROACTIVE_CONVERSATION_STARTERS": {
|
||||
"en": "Suggest Tasks on GitHub",
|
||||
"ja": "GitHubでタスクを提案",
|
||||
"zh-CN": "在GitHub上推荐任务",
|
||||
"zh-TW": "在GitHub上推薦任務",
|
||||
"ko-KR": "GitHub에서 작업 제안",
|
||||
"de": "Aufgaben auf GitHub vorschlagen",
|
||||
"no": "Foreslå oppgaver på GitHub",
|
||||
"it": "Suggerisci attività su GitHub",
|
||||
"pt": "Sugerir tarefas no GitHub",
|
||||
"es": "Sugerir tareas en GitHub",
|
||||
"ar": "اقتراح المهام على GitHub",
|
||||
"fr": "Suggérer des tâches sur GitHub",
|
||||
"tr": "GitHub'da Görevler Öner"
|
||||
},
|
||||
"SETTINGS$CUSTOM_MODEL": {
|
||||
"en": "Custom Model",
|
||||
"ja": "カスタムモデル",
|
||||
|
||||
@ -25,6 +25,8 @@ export const MOCK_DEFAULT_USER_SETTINGS: ApiSettings | PostApiSettings = {
|
||||
provider_tokens_set: DEFAULT_SETTINGS.PROVIDER_TOKENS_SET,
|
||||
enable_default_condenser: DEFAULT_SETTINGS.ENABLE_DEFAULT_CONDENSER,
|
||||
enable_sound_notifications: DEFAULT_SETTINGS.ENABLE_SOUND_NOTIFICATIONS,
|
||||
enable_proactive_conversation_starters:
|
||||
DEFAULT_SETTINGS.ENABLE_PROACTIVE_CONVERSATION_STARTERS,
|
||||
user_consents_to_analytics: DEFAULT_SETTINGS.USER_CONSENTS_TO_ANALYTICS,
|
||||
};
|
||||
|
||||
|
||||
@ -15,12 +15,14 @@ import {
|
||||
} from "#/utils/custom-toast-handlers";
|
||||
import { retrieveAxiosErrorMessage } from "#/utils/retrieve-axios-error-message";
|
||||
import { AppSettingsInputsSkeleton } from "#/components/features/settings/app-settings/app-settings-inputs-skeleton";
|
||||
import { useConfig } from "#/hooks/query/use-config";
|
||||
|
||||
function AppSettingsScreen() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { mutate: saveSettings, isPending } = useSaveSettings();
|
||||
const { data: settings, isLoading } = useSettings();
|
||||
const { data: config } = useConfig();
|
||||
|
||||
const [languageInputHasChanged, setLanguageInputHasChanged] =
|
||||
React.useState(false);
|
||||
@ -30,6 +32,10 @@ function AppSettingsScreen() {
|
||||
soundNotificationsSwitchHasChanged,
|
||||
setSoundNotificationsSwitchHasChanged,
|
||||
] = React.useState(false);
|
||||
const [
|
||||
proactiveConversationsSwitchHasChanged,
|
||||
setProactiveConversationsSwitchHasChanged,
|
||||
] = React.useState(false);
|
||||
|
||||
const formAction = (formData: FormData) => {
|
||||
const languageLabel = formData.get("language-input")?.toString();
|
||||
@ -43,11 +49,16 @@ function AppSettingsScreen() {
|
||||
const enableSoundNotifications =
|
||||
formData.get("enable-sound-notifications-switch")?.toString() === "on";
|
||||
|
||||
const enableProactiveConversations =
|
||||
formData.get("enable-proactive-conversations-switch")?.toString() ===
|
||||
"on";
|
||||
|
||||
saveSettings(
|
||||
{
|
||||
LANGUAGE: language,
|
||||
user_consents_to_analytics: enableAnalytics,
|
||||
ENABLE_SOUND_NOTIFICATIONS: enableSoundNotifications,
|
||||
ENABLE_PROACTIVE_CONVERSATION_STARTERS: enableProactiveConversations,
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
@ -90,10 +101,19 @@ function AppSettingsScreen() {
|
||||
);
|
||||
};
|
||||
|
||||
const checkIfProactiveConversationsSwitchHasChanged = (checked: boolean) => {
|
||||
const currentProactiveConversations =
|
||||
!!settings?.ENABLE_PROACTIVE_CONVERSATION_STARTERS;
|
||||
setProactiveConversationsSwitchHasChanged(
|
||||
checked !== currentProactiveConversations,
|
||||
);
|
||||
};
|
||||
|
||||
const formIsClean =
|
||||
!languageInputHasChanged &&
|
||||
!analyticsSwitchHasChanged &&
|
||||
!soundNotificationsSwitchHasChanged;
|
||||
!soundNotificationsSwitchHasChanged &&
|
||||
!proactiveConversationsSwitchHasChanged;
|
||||
|
||||
const shouldBeLoading = !settings || isLoading || isPending;
|
||||
|
||||
@ -129,6 +149,19 @@ function AppSettingsScreen() {
|
||||
>
|
||||
{t(I18nKey.SETTINGS$SOUND_NOTIFICATIONS)}
|
||||
</SettingsSwitch>
|
||||
|
||||
{config?.APP_MODE === "saas" && (
|
||||
<SettingsSwitch
|
||||
testId="enable-proactive-conversations-switch"
|
||||
name="enable-proactive-conversations-switch"
|
||||
defaultIsToggled={
|
||||
!!settings.ENABLE_PROACTIVE_CONVERSATION_STARTERS
|
||||
}
|
||||
onToggle={checkIfProactiveConversationsSwitchHasChanged}
|
||||
>
|
||||
{t(I18nKey.SETTINGS$PROACTIVE_CONVERSATION_STARTERS)}
|
||||
</SettingsSwitch>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@ export const DEFAULT_SETTINGS: Settings = {
|
||||
ENABLE_DEFAULT_CONDENSER: true,
|
||||
ENABLE_SOUND_NOTIFICATIONS: false,
|
||||
USER_CONSENTS_TO_ANALYTICS: false,
|
||||
ENABLE_PROACTIVE_CONVERSATION_STARTERS: false,
|
||||
IS_NEW_USER: true,
|
||||
};
|
||||
|
||||
|
||||
@ -21,6 +21,7 @@ export type Settings = {
|
||||
PROVIDER_TOKENS_SET: Partial<Record<Provider, string | null>>;
|
||||
ENABLE_DEFAULT_CONDENSER: boolean;
|
||||
ENABLE_SOUND_NOTIFICATIONS: boolean;
|
||||
ENABLE_PROACTIVE_CONVERSATION_STARTERS: boolean;
|
||||
USER_CONSENTS_TO_ANALYTICS: boolean | null;
|
||||
IS_NEW_USER?: boolean;
|
||||
};
|
||||
@ -37,6 +38,7 @@ export type ApiSettings = {
|
||||
remote_runtime_resource_factor: number | null;
|
||||
enable_default_condenser: boolean;
|
||||
enable_sound_notifications: boolean;
|
||||
enable_proactive_conversation_starters: boolean;
|
||||
user_consents_to_analytics: boolean | null;
|
||||
provider_tokens_set: Partial<Record<Provider, string | null>>;
|
||||
};
|
||||
|
||||
@ -33,6 +33,7 @@ class Settings(BaseModel):
|
||||
secrets_store: UserSecrets = Field(default_factory=UserSecrets, frozen=True)
|
||||
enable_default_condenser: bool = True
|
||||
enable_sound_notifications: bool = False
|
||||
enable_proactive_conversation_starters: bool = True
|
||||
user_consents_to_analytics: bool | None = None
|
||||
sandbox_base_container_image: str | None = None
|
||||
sandbox_runtime_container_image: str | None = None
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user